ES6走走看看—由块级作用域引出的一场变革

发布时间:2019-08-09 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了ES6走走看看—由块级作用域引出的一场变革脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

持续更新的gIThub笔记,链接地址:Front-End-Basics

此篇文章的笔记地址:字符到底发生了什么变化

ES6走走看看系列,特别鸣谢奇舞读书会~


块级作用域又称词法作用域,存在于:

@H_304_12@
  • 函数内部(函数作用域)
  • 块中(字符 { 和 } 之间的区域)
  • 注意:ES6允许块级作用域任意嵌套

    {{{{{{let text = 'Hello World!'}}}}}}

    因为有了块级作用域,然后我们才有继续往下聊的可能。

    1、 块级声明

    块级声明是用于声明在指定块的作用域之外无法访问的变量。

    2、 let声明:用来声明一个块级作用域变量

    1、 声明的变量具有块级作用域的特性

    // 例子
    function getValue (condition) {
        if (condition) {
            let value = 'blue';
            return value;
        }
        console.LOG(value)
        // 报错 value is not defined
    }
    getValue()

    2、 在同一个作用域内不能使用let声明同名的变量

    // 不管是VAR,const或者let,新的let声明之前同名的变量,都会报错
    var count = 30;
    let count = 40;
    // 报错 Identifier 'count' has already been declared
    
    // 函数形参和函数内部的let声明变量重名,报错
    function test(value) {
        let value = 3;
    }
    test()
    // 报错 Identifier 'value' has already been declared
    
    // 在不同的作用域声明的变量重名是没问题的
    let count = 30;
    if(true) {
      let count = 40;
      // 不同的作用域,不会报错
    }
    

    3、 声明没有预解析,不存在变量提升,有“临时死区”(TDZ)

    从块的开始变量声明这段的区域被称为临时死区,ES6明确规定,如果区块中存在letconst命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域,只要在声明之前就使用这些变量(赋值,引用等等),就会报错。

    if(true) {
        console.log(tyPEof value);
        // 报错 value is not defined
    
        let value = 'blue';
    }

    注意:TDZ是区域是“块开始”到“变量声明”,下面的例子不报错

    // typeof 说是相对安全,确实是,永远拿不到想要的结果
    console.log(typeof value); // 打印 undefined,没有报错
    if(true) {
        let value = 'red';
    }

    3、 const声明:声明常量(如PI),值一旦被设定后不可更改

    1、 常量声明的值是不可变的

    注意:const声明的对象不允许修改绑定,但可以修改该对象的属性值。

    const number = 6;
    number = 5;
    // 报错 Assignment to constant variable
    
    const obj = {number: 1};
    obj.number = 2; // 不报错
    
    obj = {number: 3};
    // 报错 Assignment to constant variable

    2、 因为常量声明后值就不可更改了,所以声明时必须赋值

    // 有效的常量
    const count = 30;
    
    // 报错 Missing initializer in const declaration
    const name;

    3、 声明的常量具有块级作用域的特性

    if(true) {
        const number = 5;
    }
    console.log(number)
    // 报错 number is not defined

    4、 在同一个作用域内不能使用const声明同名的变量

    var message = 'Hello';
    let age = 25;
    
    // 这两条语句都会报错
    const message = 'Good';
    const age = 30;

    5、 声明没有预解析,不存在变量提升,有“临时死区”(TDZ)


    总结:一张表格

    @H_463_360@
    声明方式 变量提升 作用域 是否需要初始值 重复定义
    var 函数级 不需要 允许
    let 块级 不需要 不允许
    const 块级 需要 不允许

    扩展:再提一下变量命名,不管是var、let、const声明的变量名,可以由数字,字母,下划线及美元符号组成,但是不能以数字开头。美元符号可以放到任何一个位置,甚至单独一个美元符号。

    4、 循环中的块作用域绑定

    循环中的let声明@H_24_406@
    // 第一个对比
    // before
    for(var i = 0; i < 5; i++) {
        // ... 省略一些代码
    }
    console.log(i)  // 5
    
    //after
    for(let i = 0; i < 5; i++) {
        // ... 省略一些代码
    }
    console.log(i) // 报错 i is not defined
    
    
    // 第二个对比
    // before
    var funcs = [];
    for(var i = 0; i < 10; i++) {
        funcs.push(() => {console.log(i)})
    }
    funcs.forEach((ele) => {
        ele()
    })
    // 打印 10次 10
    
    // after
    var funcs = [];
    for(let i = 0; i < 10; i++) {
        funcs.push(() => {console.log(i)})
    }
    funcs.forEach((ele) => {
        ele()
    })
    // 打印 0 1 2 3 4 5 6 7 8 9

    注意:有一点重要,let 声明在循环内部的行为是标准中专门定义的,它不一定与 let 不提升特性有关。

    循环中的const声明
    // for 循环会报错
    for (const i = 0; i < 1; i++) {
        console.log(i)
    }
    // 打印 0 ,然后报错 Assignment to constant variable.
    
    // for-in 和 for-of 不会报错
    var object = {
        a: true,
        b: true,
        c: true
    };
    for (const key in object) {
        // 不要在循环体内更改key的值,会报错
        console.log(key)
    }
    // 打印 a b c

    注意:const可以应用在 for-in 和 for-of 循环中,是因为每次迭代不会修改已有绑定,而是会创建一个新绑定。

    5、 块级绑定最佳实践的进化

    ES6 早期

    普遍认为默认使用let来替代var,对于写保护的变量使用const

    ES6 使用中

    普遍默认使用const,只有确实需要改变变量的值时使用let。因为大部分变量的值在初始化后不应再改变,而预料之外的变量值的改变是许多bug的头。这样就可以在某种程度上实现代码的不可变,从而止某些错误的发生。

    6、 全局变量将逐步与顶层对象的属性脱钩

    顶层对象,在浏览器环境指的是window对象,在Node指的是global对象。

    为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;

    var a = 1;
    window.a // 1

    ES6走走看看—由块级作用域引出的一场变革

    另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

    ES6走走看看—由块级作用域引出的一场变革

    上图可见let 声明的变量,并没有在Window对象里,而是一个新的Script对象。

    扩展:如果需要在浏览器中跨framewindow访问代码,仍然可以用var在全局对象下定义变量。

    7、 块级函数

    ECMAScript 6开始,在严格模式下,块里的函数作用域为这个块。ECMAScript 6之前不建议块级函数在严格模式下使用。

    'use strict';
    
    function f() {
      return 1;
    }
    
    {
      function f() {
        return 2;
      }
    }
    
    f() === 1; // true
    
    // f() === 2 在非严格模式下相等

    注意:在非严格模式下不要用块级函数,因为在非严格模式下,块中函数的声明表现奇怪,有兼容性风险

    if (shouldDefineZero) {
       function zero() {     // DANGER: 兼容性风险
          console.log("This is zero.");
       }
    }

    ecmascript 6中,如果shouldDefineZero是false,则永远不会定义zero,因为这个块不执行。这是新标准定义的。然而,这里存在历史遗留问题,无论这个块是否执行,一些浏览器会定义zero。

    在严格模式下,所有支持ECMAScript 6的浏览器以相同的方式处理:只有在shouldDefineZero为true的情况下定义zero,并且作用域只是这个块内。

    脚本宝典总结

    以上是脚本宝典为你收集整理的ES6走走看看—由块级作用域引出的一场变革全部内容,希望文章能够帮你解决ES6走走看看—由块级作用域引出的一场变革所遇到的问题。

    如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。