考虑一下以下的代码片段:

for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.addEventListener('click', function(){ console.log(i); });
document.body.appendChild(btn);
}

(a)当用户点击“Button4”的时候会打印什么?并解释为什么?

(b)提供一个或多个正确的实现方式。

答:(a)无论点击哪个按钮,都将打印5.因为任何按钮在调用onclick方法时,for循环已经完成了,变量i的值变成了5.

  (b)关键是要抓住在每一次循环for的时候要把i的值传人到最近创建的函数对象中。

下面有三个可能的方式解决这个问题:

//方法1:作为函数参数调用
for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.addEventListener('click', (function(i) {
return function() { console.log(i); };
})(i));
document.body.appendChild(btn);
} //方法2:将整个btn.addEventListener封装在一个新的匿名函数里
for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
(function (i) {
btn.addEventListener('click', function() { console.log(i); });
})(i);
document.body.appendChild(btn);
} //方法3:将for循环换成array对象的本地调用方法forEach.
['a', 'b', 'c', 'd', 'e'].forEach(function (value, i) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.addEventListener('click', function() { console.log(i); });
document.body.appendChild(btn);
});

For循环和闭包问题的更多相关文章

  1. 说说循环与闭包——《你不知道的JS》读书笔记(一)

    什么是闭包 <你不知道的JS>里有对闭包的定义:"当函数可以记住并访问所在的词法作用域,即使函数是在当前作用域之外执行,这就产生了闭包." 讲闭包是啥的太多了...就一 ...

  2. JavaScript中的循环和闭包

    看一段比较经典的错误代码: // 希望获取页面上的所有div,在点击的时输出对应的编号 var oDom = document.querySelectorAll("div"); / ...

  3. golang 循环创建闭包 问题排查

    ][]string{ { { "邀请码是什么", "我没有邀请码", "这个邀请码我可以随便填吗", "邀请码可以填他的手机号吗& ...

  4. for循环与闭包

    Es5 function box(){ var arr = []; ;i<;i++){ arr[i] = (function(num){ //自我执行,并传参(将匿名函数形成一个表达式)(传递一 ...

  5. JS for循环 闭包

    对于for循环的闭包问题的理解,认为需要理解函数中的变量的作用域链的概念 另外提及下变量提升的概念 如下例子: var ar = [];for(var i=1:i<10; i++){ ar[i] ...

  6. JS中for循环里面的闭包问题的原因及解决办法

    我们先看一个正常的for循环,普通函数里面有一个for循环,for循环结束后最终返回结果数组 function box(){ var arr = []; for(var i=0;i<5;i++) ...

  7. 《你不知道的JavaScript》整理(一)——作用域、提升与闭包

    最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 ...

  8. javascript中的闭包、模块与模块加载

    一.前言 闭包是基于词法作用域(  和动态作用域对应,词法作用域是由你写代码时,将变量写在哪里来决定的,因此当词法分析器处理代码时,会保持作用)书写代码时所产生的自然结果,甚至不需要为了利用闭包而有意 ...

  9. javascript最容易混淆的作用域、提升、闭包

    一.函数作用域 1.函数作用域 就是作用域在一个“Function”里,属于这个函数的全部变量都可以在整个函数的范围内使用及复用. function foo(a) { var b = 2; funct ...

随机推荐

  1. (转)NodeJS - 第一个应用程序Hello World

    安装NodeJs 在创建实际的“Hello,World!”应用之前,我们应该先安装NodeJS,安装NodeJS可以访问NodeJS官网,下载相应系统的NodeJS的安装包,进行安装. 程序组件 关于 ...

  2. opensuse 通过composer安装drush工具

    由于笔者的opensuse已安装好composer,所以按照官方网站的文章 Installing/Upgrading Drush on Ubuntu,使用composer形式安装drush工具. co ...

  3. import: not authorized `time' @ error/constitute.c/WriteImage/1028. import: not authorized `rospy' @ error/constitute.c/WriteImage/1028.

  4. python 编程 一次错误记录 -1073740791

    原因是发生在我错把类当做实例化对象使用了

  5. 转-Pycharm中运行Python代码的几种方式

    转自:Pycharm中运行Python代码的几种方式 在pycharm中的Python代码运行会出现各种奇葩的问题,比如,密码输入时不显示或没有提示,给我们带来一些麻烦,下面介绍几种代码运行的几种方式 ...

  6. C++之memset函数

    可参考: C++中memset函数的用法 C++中memset函数的用法 C++中memset()函数的用法详解 c/c++学习系列之memset()函数 透彻分析C/C++中memset函数 mem ...

  7. Autowire(自动装配)机制

    为什么Spring要支持Autowire(自动装配) 先写几个类,首先定义一个Animal接口表示动物: 1 public interface Animal { 2 3 public void eat ...

  8. Hack Tools

    Tools 2011-03-17 13:54:36|  分类: Security|举报|字号 订阅     Packet Shaper:Nemesis: a command line packet s ...

  9. python 编码问题:'ascii' codec can't encode characters in position 的解决方案

    报错: 'ascii' codec can't encode characters in position 8-50: ordinal not in range(128) Python在安装时,默认的 ...

  10. 2018-8-10-docfx-做一个和微软一样的文档平台

    title author date CreateTime categories docfx 做一个和微软一样的文档平台 lindexi 2018-08-10 19:16:51 +0800 2018-2 ...