for ( i = 0 ; i < 10 ; i ++ ) { var a = document . createElement ( 'a' ) ; a . innerHTML = i + '<br>' ; a . addEventListener ( 'click' , function ( e ) { alert ( i ) ; } ) ; document . body . appendChild ( a ) ;
    for (let i = 0; i < 10; i++) {
        var a = document.createElement('a');
        a.innerHTML = i + '<br>';
        a.addEventListener('click', function (e) {
            alert(i);
        });
        document.body.appendChild(a);

上面两种写法完全不同,第一种弹出来的全是10,第二种会弹出对应的数字。

原因是a.addEventListener(‘click’, () => {} ) 是一个异步函数,当for循环函数执行完成后才可以执行点击事件,此时点击的时候才会触发回调函数,然后i去当前作用域下去寻找i的值,如果没有则去父作用域去寻找对应的值。

第一种写法在for循环内没有定义i,而是在for循环的上一层定义的,也就是for循环执行完成之后i的值变成了10;
而第二种写法是在for的作用域内定义了变量,那么回调函数里的i就会找到for循环作用域内定义的变量i,此时可以输出对应的数值。

对第一种进行改进:

 	let i;
    for (i = 0; i < 10; i++) {
        (function name(i) {
            var a = document.createElement('a');
            a.innerHTML = i + '<br>';
            a.addEventListener('click', function (e) {
                alert(i);
            });
            document.body.appendChild(a);
        })(i);

上面的改进后的代码可以的原因是因为加入了一个函数,将变量注入到一个函数作用域内了。

实际开发中闭包的应用

function isFirstLoad() {
        var _list = [];
        return function(id) {
            if (_list.indexOf(id) >=0) {
                return false;
            } else {
                _list.push(id);
                return true;
    var firstLoad = isFirstLoad();
    console.log(firstLoad(10));
    console.log(firstLoad(10));
    console.log(firstLoad(20));
    console.log(firstLoad(20));
let i;
for (i = 0; i < 10; i++) {
    var a = document.createElement('a');
    a.innerHTML = i + '<br>';
    a.addEventListener('click', function (e) {
        console.log(b) // 不会报错,只要当点击的时候才会报错,因为JavaScript是解释型脚本
        alert(i);
    });
    document.body.appendChild(a);
                    作用域链	let i;    for (i = 0; i &lt; 10; i++) {        var a = document.createElement('a');        a.innerHTML = i + '&lt;br&gt;';        a.addEventListener('click', function (e) {            alert(i);        });        document.body.appendChild(a); 
				
作用域闭包JavaScript里非常重要。但是在我最初学习JavaScript的时候,却很难理解。这篇文章会用一些例子帮你理解它们。 我们先从作用域开始。 JavaScript作用域限定了你可以访问哪些变量。有两种作用域:全局作用域,局部作用域。 全局作用域 在所有函数声明或者大括号之外定义的变量,都在全局作用域里。 不过这个规则只在浏览器中运行的JavaScript里有效。如果你在Node.js里,那么全局作用域里的变量就不一样了,不过这篇文章不讨论Node.js。 `const globalVariable = 'some value'` 一旦你声明了一个全局变量,那么你在
JavaScript作用域闭包1. 作用域作用域链1.1 作用域1.2 作用域链2. 闭包2.1 闭包怎么设计?2.2 eval2.3 给闭包下个定义2.4 闭包的缺点2.4.1 详细分析2.5 总结 1. 作用域作用域链 1.1 作用域 变量保存和访问的范围。在JavaScript中,函数,块,模块都可以形成作用域作用域全称是词法作用域,是在代码编写时就确定了作用域的。 1.2 作用域链 函数之间的嵌套会形成作用域链。 比如说在全局作用域中定义了一个函数f1,又在f1中定义了一个内部函数f2,
作用域闭包 尽管通常将JavaScript归类为“动态”或“解释执行”语言,但实际上它是一门编程语言。但与传统的编译语言不同,它不是提前编译的,编译结果也不能在分布式系统中进行移植。尽管如此,JavaScript引擎进行编译的步骤和传统的编译语言非常相似,在某些环节可能比预想的复杂。 传统的编译语言通常会在一段源代码执行之前经历三个步骤,统称为“编译”。这三个步骤分别是分词/词法分析(Tokenizing/Lexing)、解析/语法分析(Parsing)、代码生成。但对于JavaScript来说,大部分情