ES6作用域(let,给按钮循环添加点击事件问题)

探讨ES5中变量作用域的问题及解决方案,并介绍ES6引入let关键字以创建块级作用域,解决循环和条件语句中的变量污染问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ES5之前存在的问题:因为if和for都没有块级作用域的概念,所以很多时候都必须借助函数的作用域来解决使用外面变量的问题。

    // 1.变量作用域:变量在什么范围内可用,但是使用var时没有作用域,上述都能够打印出why
    {
      var name = 'why';
      console.log(name);
    }
    console.log(name);

```javascript
    //2没有块级作用域引起的问题:if的块级
    var fun;
    if(true){
      var name='lee';
      fun = function(){
        console.log(name);
      }
      fun();//打印出lee
    }
   //假如在外面使用fun(),本意想输出if中的name,
   //但是name在外面可以任意改变
    name='修改lee';
    fun();//修改lee
    //3没有块级作用域引起的问题:for没作用域,经典按钮问题
    var btns = document.getElementsByTagName('button');
    for(var i = 0;i<btns.length;i++){
      btns[i].addEventListener('click',function(){
        console.log(i);
      })
    }
    // 不管点击什么按钮都是5
    // i循环结束后变成五,又由于for没有块级作用域问题,不会将每次的i保存在作用域中,最后点击的时候,i就从外面获取i的值,而此时i已经变为5了,在真正使用i之前,i发生了改变。与上述if的例子相同,i值可以在下次循环的时候发生改变,而不会保持原来在一个for循环中的值。

以前解决办法:写闭包,因为函数具有作用域:

    var btns = document.getElementsByTagName('button');
    for (var i = 0; i < btns.length; i++) {
      (function (i) {
        btns[i].addEventListener('click', function () {
          console.log(i);
        })
      })(i)
    }

在这里插入图片描述
相当于:

    function(i){//i=0
      btns[i].addEventListener('click', function () {
        console.log(i);
      })
    }
    function(i){//i=1
      btns[i].addEventListener('click', function () {
        console.log(i);
      })
    }

ES6中,加入了let,let是有if和for的块级作用域

    var btns = document.getElementsByTagName('button');
    //将var i = 0 改为 let i = 0 就可以实现功能
    for(let i = 0;i<btns.length;i++){
      btns[i].addEventListener('click',function(){
        console.log(i);
      })
    }

由于let具有块级作用域,相当于(都有自己独立的作用域):

    {i=0
      btns[i].addEventListener('click', function () {
        console.log(i);
      })
    }
    {i=1
      btns[i].addEventListener('click', function () {
        console.log(i);
      })
    }
### 如何在原生 JavaScript 中通过循环点击事件递参数 在原生 JavaScript 中,可以通过 `addEventListener` 方法绑定事件监听器,并利用闭包来实现动态参的功能。以下是详细的说明以及代码示例。 #### 使用闭包解决循环中事件绑定的问题 当在一个循环中为多个元素绑定事件时,如果直接使用索引变量作为参数,则可能会因为闭包的作用导致最终所有的回调函数都获取到相同的值(通常是最后一次迭代后的值)。为了避免这种情况,可以创建一个新的作用域,在每次迭代时捕获当前的值[^1]。 下面是一个具体的实现方式: ```javascript // 创建一组按钮用于测试 const container = document.getElementById('container'); for (let i = 0; i < 5; i++) { const button = document.createElement('button'); button.textContent = 'Button ' + i; container.appendChild(button); // 使用立即执行函数表达式(IIFE)捕获当前i的值 (function(index) { button.addEventListener('click', function(event) { console.log(`Clicked Button ${index}`, event); // 输出被点击按钮的信息 }); })(i); } ``` 上述代码片段展示了如何通过 IIFE(Immediately Invoked Function Expression)来锁定每一次循环中的 `i` 的值,从而确保每个按钮都能正确地打印其对应的编号[^3]。 #### 利用 let 关键字替代 var 避免闭包陷阱 现代浏览器支持 ES6 及以上版本的标准语法,其中引入了块级作用域的关键字 `let` 和 `const`。这些关键字可以帮助开发者更方便地避免因共享变量而导致的问题。例如: ```javascript const buttons = Array.from(document.querySelectorAll('.buttons')); buttons.forEach((btn, index) => { btn.addEventListener('click', (event) => { console.log(`You clicked on button number: ${index}`, event.target); // 正确输出对应序号 }); }); ``` 在这个例子中,由于 `forEach` 函数内部声明的是基于块级作用域的变量 `index`,因此不需要额外的操作即可保证每一轮循环都有独立的副本[^4]。 #### 结合实际场景应用实例 假设我们需要开发一个小功能:页面上有若干选项卡,点击某个选项卡会切换至相应的页面内容区域。这里给出一种可能的解决方案——借助数据驱动的方式完成此需求[^2]。 HTML结构部分: ```html <div id="tabBar"> <!-- 动态生成 --> </div> <div id="contentArea"></div> ``` JavaScript逻辑部分: ```javascript (function setupTabs() { const options = ['Home', 'About', 'Contact']; const tabBar = document.getElementById('tabBar'); const contentArea = document.getElementById('contentArea'); options.forEach((optionName, idx) => { const tabItem = document.createElement('div'); tabItem.className = 'tab'; tabItem.textContent = optionName; tabItem.addEventListener('click', () => showContent(idx)); tabBar.appendChild(tabItem); }); function showContent(selectedIdx) { contentArea.innerHTML = `<p>Now showing page: ${selectedIdx}</p>`; } })(); ``` 这段脚本首先定义了一个数组表示各个标签页名称;接着遍历该数组并针对每一个项构建 DOM 节点同时附加 click 处理程序;最后提供一个辅助函数负责更新主要内容区的内容展示。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值