• ECMAScript 6学习笔记(二):let和块级作用域


    同步发布于:https://mingjiezhang.github.io/(转载请说明此出处)。

    ES6中加入了let,也让JavaScript拥有了块级作用域。

    没有块级作用域的JavaScript

    在ES5及其之前的版本里,作用域只有全局作用域和函数作用域两种,而不像其他许多语言一样还拥有块级作用域。没有块级作用域的JavaScript在使用的过程中出现了许多意想不到的具体问题,比如下面这段代码的demo:

    var arr = [];
    for (var i = 0; i < 10; i++) {
      arr[i] = function () {
        console.log(i);
      };
    }
    arr[3]();
    

    如果是学过C++或者其他有块级作用域的人,可能类比觉得上述代码会输出3,不过事实上该代码输出的是10。

    因为ES5及之前是没有块级作用域的,i所处的仍是全局作用域而不是块级作用域。因此,循环过程中数组arr的每个数组项所引用的函数中的变量i都是引用全局作用域中的i,因此arr3中i为for循环结束时的i的值10。

    对于该问题,有很多方法解决。比如可以将for循环体的代码放入一个立即执行函数中,相当于创建一个新的作用域,将i当做实参传入里及执行函数,本质上是创造了一个模拟的块级作用域,当然也可以认为为内部的函数创建一个闭包(闭包的本质和作用域链息息相关)。

    let的出现

    现在我们再写之前的那段代码是,有了更加简洁的方法,使用ES6的let。

    var arr = [];
    for (let i = 0; i < 10; i++) {
      arr[i] = function () {
        console.log(i);
      };
    }
    arr[3](); //3
    

    let的出现使得JavaScript终于拥有了块级作用域。因为ES6要考虑之前版本的兼容,所以是通过声明let来使用块级作用域。

    当我们在一个代码块中使用let来声明变量,通过let声明的变量只在当前块作用域中有效。

    {
      let a = 1;
      var b = 2;
    }
    console.log(a); //ReferenceError
    console.log(b); //2
    

    如上,let的声明方式让let所在的块成为块级作用域,同时let声明的变量无法在全局作用域中访问到,但是var变量依旧可以在全局作用域访问到。

    无变量提升

    let中不存在变量提升的现象。变量在使用之前必须被声明。

    因此,这个定义也导致了暂时性死区的现象。

    var c = 'test';
    if (true) {
      c = 'new'; //ReferenceError
      let c;
      console.log(c);
    }
    

    如上在块级块级作用域中重新声明全局作用域中的c时,这时,编译器会屏蔽全局作用域中的c,在该块级作用域中只能使用新声明的c。但由于块级作用域中let声明的变量无作用域提升现象,因此无法在声明c之前使用c(包括赋值c),出现暂时性死区的现象。

    块级作用域

    let的出现让JavaScript可以充分利用块级作用域的特性。我们可以在不同的块级作用域中使用同名变量。

    if (true) {
    	let a = 1;
    	if(true){
            let a = 2;
            console.log(a); //2
        }
        console.log(a); //1
    }
    

    由于块级作用域出现,我们可以实现上述变量隔离的效果。

    总结

    let在不影响var使用的情况下,开创了JavaScript的块级作用域,未来想必let也会大量取代var的使用。

    欢迎指正交流。未经允许,请勿转载。

  • 相关阅读:
    自动同步日期dos命令 | DOS命令自动同步时间
    Mysql字符串截取,去掉时间,匹配日期等于今日
    HTML指定页面编码
    Mysql连接字符,字段函数concat()
    功能强大的截图工具snipaste
    当页面提交时,执行相关JS函数检查输入是否合法
    DOM和BOM
    JS内建對象(Math,Number,String,Date)
    JS数组基础01(数组的创建,push,pop,unshift,shift,concat,join,splice,slice,sort.reverse,indexOf,三种排序)
    总结01(对象引用的赋值与对象的复制,函数作为对象及回调递归,区分数组与对象)
  • 原文地址:https://www.cnblogs.com/mingjiezhang/p/5940172.html
Copyright © 2020-2023  润新知