this.value; // 试试
题主的 for 循环跑完后,实际上:
i=5 btn = 最后一个 input
为什么这样呢,我们来看下代码,稍微改了下:
for(var i=0;i<5;i++){ var btn=document.createElement('input'); btn.setAttribute('type','button'); btn.setAttribute('value','btn'+i); document.body.insertBefore(btn,document.body.firstElementChild); //直接插入到文档最前面,方便测试 btn.onclick=function(){ alert(btn.value); }; }
要知道 es6 之前是没有块级作用域的,且
用 var 定义的变量会有一个声明提升的特性,这个动作开始于代码执行之前,会将 var 定义的变量提升到所在函数或全局环境的顶端,但是赋值操作仍然停留在原地
题主的代码其实相当于:
var i,btn; for(i=0;i<5;i++){ btn=document.createElement('input'); btn.setAttribute('type','button'); btn.setAttribute('value','btn'+i); document.body.insertBefore(btn,document.body.firstElementChild); btn.onclick=function(){ alert(btn.value); }; } console.log(btn); // btn 被赋值了5次,覆盖了4次,最后一个是 btn4,所以很显然是最后一个 console.log(i); // i=5的时候跳出循环,所以 i 最后一个值是 5
这样是不是就很好理解了?
因为你给 btn 绑定的事件处理程序(回调函数)并不是马上执行,触发的时候才执行,这个时候 btn 已经被覆盖了4次,变成最后一个 btn 了;
核心原因是: var 有声明提前的特性。如要改的话,有多种方式,这里暂就说两种:法一:btn 改为 this (推荐)
for(var i=0;i<5;i++){ var btn=document.createElement('input'); btn.setAttribute('type','button'); btn.setAttribute('value','btn'+i); document.body.insertBefore(btn,document.body.firstElementChild); btn.onclick=function(){ alert(this.value); }; }
在事件绑定中,如果事件处理程序(也就是回调函数)中没有嵌套的函数,事件绑定在谁身上,this 就指向谁,如果回调里还有嵌套函数,this 默认指向全局对象,所以这里 this 就指向了绑定时的那个 btn;不明白戳这法二:用 let 代替 var
for(var i=0;i<5;i++){ let btn=document.createElement('input'); btn.setAttribute('type','button'); btn.setAttribute('value','btn'+i); document.body.insertBefore(btn,document.body.firstElementChild); btn.onclick=function(){ alert(btn.value); }; }
这是 ES6 的内容,详细理解戳这:深入理解ES6-中
因为你每次for循环的时候,给按钮添加了点击事件,同时btn也会指向不同的按钮,在最后一次循环的时候,btn指向了最后一个按钮,所以每次输出的都是4
或许你可以把里面的点击事件包成匿名函数自执行然后传参,也可以应用ES6里面的let 声明循环变量,因为在每一个{}中都是一个let作用域
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
暂无简介
文章 0 评论 0
接受
发布评论
评论(4)
题主的 for 循环跑完后,实际上:
为什么这样呢,我们来看下代码,稍微改了下:
要知道 es6 之前是没有块级作用域的,且
题主的代码其实相当于:
这样是不是就很好理解了?
核心原因是: var 有声明提前的特性。如要改的话,有多种方式,这里暂就说两种:
法一:btn 改为 this (推荐)
在事件绑定中,如果事件处理程序(也就是回调函数)中没有嵌套的函数,事件绑定在谁身上,this 就指向谁,如果回调里还有嵌套函数,this 默认指向全局对象,所以这里 this 就指向了绑定时的那个 btn;不明白戳这
法二:用 let 代替 var
这是 ES6 的内容,详细理解戳这:深入理解ES6-中
因为你每次for循环的时候,给按钮添加了点击事件,同时btn也会指向不同的按钮,在最后一次循环的时候,btn指向了最后一个按钮,所以每次输出的都是4
或许你可以把里面的点击事件包成匿名函数自执行然后传参,也可以应用ES6里面的let 声明循环变量,因为在每一个{}中都是一个let作用域