zoukankan      html  css  js  c++  java
  • ES6语法:let作用域

    1.历史

    ES6全程ECMAScript 6,参考书籍:ECMAScript 6入门 作者:阮一峰

    在有js基础上,更好的理解ES6.

    1996年11月,Netscape公司创造了Javascript,次年,被国际标准化组织(ECMA)定为国际标准。

    该标准针对JavaScript,为避免版权冲突,这个标准被命名为ECMAScript,简称ES.

    随着版本更替,2015年的ES2015做出了大幅度的改变,开始制定ES6规则,象征着新标准的改变,此后,ES6不仅仅表示了2015年的ES2015标准,也代表了“下一代JavaScript语言”。

    2.配置

    1)Babel转码器

    Babel可以将ES6代码转化为ES5代码,从而支持老版本浏览器的执行。

    例如:ES6标准写法:input.map(item => item + 1);通过Bable转码后:input.map(function (item) {  return item + 1; });

    上述 => 的写法就是ES6写法,代替了函数返回。

    2)polyfill

    Babel默认只转换新的JS语法,而不转换新的API。比如ES6中新的API:Set,Map,Proxy,Aymbol等全局对象。需要安装core-jsregenerator-runtime为当前环境提供一个垫片。

    但是需要注意一点,网页实时将ES6转换为ES5对性能会有影响。因此,生产环境需要加载已经转完码的脚本。

    3.新语法

    1)let命令

    ES6新增的let命令类似于var,区别的是,var是全局变量,一处定义,全局有效。但let的语法只在代码块,作用域内有效,而且,只能先定义后使用。对于同一变量,let不允许重复定义,但var却可以。例如:

    {
    
    let a = 10;
    
    var b = 10;
    
     
    
    }
    
    alert(a); //错误,a只能在上面{}的作用域内有效
    
    alert(b); //正确,var全局有效

    例如2:

    {
    
    alert(a); //错误,a是下面的let定义的变量,let定义的变量只能在他后面使用,在定义前使用是错误的,在这定义前的区域称为死区。
    
    alert(b); //正确,var全局有效,不分定义先后顺序。这种不分顺序的原因其实是种“变量提升”现象,即变量可以在声明之前使用。
    let a = 10;
    
    var b = 10; 
    
    }

    那么,为什么要有let这个语法呢,var多方便啊,随便用的。正因随便二字使得var没有规范,可能使用的变量不知道在哪里已经定义过了,我们因该遵循哪里要用,那里定义,别处不能使用的原则,例如:

    for循环中,使用let就很合适

    for( let i = 0; i < 10; i ++){ console.log(i); }

    这里很明显,我定义的i变量只希望用在for循环里面,除了for循环我用不到,也不希望别人误用,let定义的变量就比var好多了。

     2)块级作用域

    其实在上述中已经有提到块级作用域了{},块级作用域就是为了避免一处定义全局可用的现象,我明明只希望在for循环中使用这个变量,结果for循环外你也能使用了,这不是泄露了我的变量了吗,再说,如果我定义完了变量,你在后面又重复定义了我的变量,这不是改变了我的变量了吗,这不乱套了。比如:

    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';
      }
    }
    
    f(); // undefined

    上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

    块级作用域的用法:

    function f1() {
      let n = 5;
      if (true) {
        let n = 10;
      }
      console.log(n); // 5
    }

    上面的函数有两个代码块,都声明了变量n,运行后输出 5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是 10。

    上面是变量的作用域,函数也是一样的,但这里有一个很大的不同:

    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());

    上面代码在 ES5 中运行,会得到“I am inside!”,因为在if内声明的函数f会被提升到函数头部。

    ES6 就完全不一样了,理论上会得到“I am outside!”。因为块级作用域内声明的函数类似于let,对作用域之外没有影响。但是,如果你真的在 ES6 浏览器中运行一下上面的代码,是会报错的。

    原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式:

    • 允许在块级作用域内声明函数。
    • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
    • 同时,函数声明还会提升到所在的块级作用域的头部。

    因此,考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

    // 块级作用域内部的函数声明语句,建议不要使用
    {
      let a = 'secret';
      function f() {
        return a;
      }
    }
    
    // 块级作用域内部,优先使用函数表达式
    {
      let a = 'secret';
      let f = function () {
        return a;
      };
    }

    另外需要注意的是,ES6使用{}表示块级作用域的,如果没有{}会认为不存在块级作用域,这时使用let会报错,因为找不到作用域。

  • 相关阅读:
    Eclipse下搭建Django环境
    在pycharm中启动Django服务器
    Window10安装Django,并创建第一个Django项目
    windows10安装tensorflow CPU版本
    service中显示一个dialog
    xp局域网共享访问没权限处理
    java线程调度
    Java优雅停机
    jit编译原理
    java final思考
  • 原文地址:https://www.cnblogs.com/lvqiang/p/14652938.html
Copyright © 2011-2022 走看看