A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 dkxhy 于 2017-12-8 15:40 编辑

    ES6已经出来很久了,应用也越来越广泛,而且面试中也越来越多的问道有关es6的东西。今天,我们来学习一下es6总let的实现原理。在学习之前,我们先看一下let的特点:

1, 块级作用域
2,无变量提升
3,暂时性死区
4,不允许重复声明
  这篇帖子主要看一下块级作用域的原理。
一,块级作用域
先来看一个非常经典的例子
----例1----
[JavaScript] 纯文本查看 复制代码
 var a=[];
               for(var i=0;i<10;i++){
                   a[i]=function(){
                       console.log(i);
                   };
               }
  [/i]             a[6](); //10  
这是最常见的写法,我们来看一下代码的执行过程。
var i=0;//此时的var定义的变量是全局的。
a[0]=function(){
    console.log(i);//这里之所以i为i而不是0;是因为我们只是定义了该函数,未被调用,所以没有进入该函数执行环境,i当然不会沿着作用域链向上搜索找到i的值。
}


var i=1;//第二次循环,因为是全局的, i=1;覆盖了前面的 i=0;即现在i为1;
a[1]=function(){
    console.log(i);//解释同a[0]函数。
}var i=2;// 第三次循环,这时 i=2,在全局作用域中,所以覆盖了前面的i=1;
a[2]=function(){
    console.log(i);
}
......第四次循环 此时i=3  这个以及下面的i不断的覆盖前面的i,因为都在全局作用域中
......
......第九次循环 此时i=8


var i=9;
a[9]=function(){
    console.log(i);
}


var i=10;// 这时i为10,因为不满足循环条件,所以停止循环。

紧接着在全局环境中继续向下执行。

       a[6]();//这时调用a[6]函数,所以这时随即进入a[6]函数的执行环境,即a[6]=function(){console.log(i)};
执行函数中的代码 console.log(i); 因为在函数执行环境中不存在变量i,所以此时会沿着作用域链向上寻找,即进入了全局作用域中寻找变量i,而全局作用域中i=10覆盖了前面所有的i值,所以说这时i为10,那么a[6]的值就是10了。----例2----
[JavaScript] 纯文本查看 复制代码
 var a=[];
    for(let i=0;i<10;i++){
[i]        a=function(){
            console.log(i);
        };
    }
    a[6]();    //6
{ //进入第一次循环
    let i=0; //注意:因为使用let使得for循环为块级作用域,此次let i=0在这个块级作用域中,而不是在全局环境中。
    a[0]=function(){
        console.log(i);
     }; //注意:由于循环时,let声明i,所以整个块是块级作用域,那么a[0]这个函数就成了一个闭包。
}// 声明: 我这里用{}来模拟块级作用域的存在。   


{ //进入第二次循环
     let i=1; //注意:因为let i=1; 和 上面的let i=0;出在不同的作用域中,所以两者不会相互影响。
     a[1]=function(){
         console.log(i);
     }; //同样,这个a也是一个闭包
}

......进入第三次循环,此时其中let i=2;
......
......进入第九次循环,此时其中let i=8;

{//进入第十次循环
    let i=9;
    a=function(){
        console.log(i);
    };//同样,这个a也是一个闭包
}

a[6]();//调用a[6]()函数,这时执行环境随即进入下面这个代码块中的执行环境:funcion(){console.log(i)};

{
     let i=6;
     a[6]=function(){
          console.log(i);
     }; //同样,这个a也是一个闭包
}
    每次for循环都会创建一个{}块级作用域,相当于在内存中又重新开了一块区域去存储变量和函数,不会互相影响。执行a[6]时,首先在当前函数内部找这个变量,没有的话会沿着作用域链向上找,
当前作用域内有i= 6,就直接使用。因此,打印结果为6.


相信大家仔细看完上面的函数执行的过程,对let var 块级作用域 闭包就有一个很好的理解了。我认为重要的是对于函数执行过程的理解!



1 个回复

倒序浏览
优秀,奈斯
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马