美文网首页让前端飞JavaScript 进阶营
重读《深入理解ES6》—— 块级作用域

重读《深入理解ES6》—— 块级作用域

作者: 零和幺 | 来源:发表于2019-03-06 00:48 被阅读3次

一、关于变量声明提升

在 ES5 中,我们通常会使用 var 来声明变量。在使用 var 声明变量的时候,通常会遇到变量声明提升的问题。这种机制会让很多初学者疑惑不解。其实当我们理解了一个变量通常包括声明赋值两个部分,这个问题也就不难理解了。

    // 1
    console.log(a); // undefined
    var a = 3;
    
    // 2
    function foo() {
        console.log(b);  // undefined
        if (true) {
            var b = 2;
        }
    }

事实上,无论在全局作用域或者函数作用域中,只要通过 var 关键字声明的变量,不论在哪里声明,都会被当成在当前作用域顶部声明的变量。

    // 1
    var a;
    console.log(a);
    a = 3;
    
    // 2
    function foo() {
        var b;
        console.log(b);
        if (true) {
            b = 2;
        }
    }

二、块级作用域

其实,变量提升的机制,不太符合我们的编码习惯,我们常常希望代码能够按照顺序执行,这也符合一般人的逻辑习惯。为此 ES6 引入了块级作用域的概念。

块级作用域其实就是词法作用域,我们的代码写在哪,就会在哪里执行,这更符合我们的编程习惯。我们常说的块包括函数内部{}之间的部分

为了实现块级作用域,ES6 采用 letconst 代替 var 来声明变量。用 letconst 声明的变量会把变量的作用域限制在当前的代码块中,并且声明的变量不会被提升。另外,用 let 声明的变量,在同一代码块内,禁止重复声明。

    // 1、变量不会提升
    console.log(a); // ReferenceError: a is not defined
    let a = 3;
    
    // 2、变量只能在当前作用域访问
    if (true) {
        const b = 3;
        console.log(b); // 3
    }
    console.log(b); // ReferenceError: b is not defined
    
    // 3、禁止重复声明
    function foo() {
        let c = 3;
        let c = 4; // Identifier 'c' has already been declared
    }
    foo();

三、let 与 const 的区别

letconst 都可以创建一个块级作用域,唯一的区别是 const 用来声明一个常量,它的值一旦被设定后不可修改。所以,用 const 声明的常量必须初始化。

    // 1、不可更改
    const a = 1;
    a = 2; // TypeError: Assignment to constant variable.
    
    // 2、必须初始化
    const b; // SyntaxError: Missing initializer in const declaration

关于 const 声明的变量不可修改,有一个值得注意的地方就是用 const 声明一个对象。比如:

    const tom = {
        age: 18,
        city: 'shanghai'
    };
    
    tom.age = 19; // 这是可以的

我们可以理解为,用 const 声明了一个变量 tom,将一个对象的引用地址赋值给变量 tom,只要这个引用地址不发生变化,内部的值是可以修改的。

四、循环中块级作用域

在 ES5 中,比较让人头疼的地方可能就是 for 循环了。在循环中,我们用 var 声明一个变量,循环结束后,我们其实是希望这个变量被销毁的。但由于 var 声明的变量具有声明提升的特性,所以当我们用 for 循环的时候,往往会污染我们的全局作用域。

    for (var i = 0; i < 10; i++) {
        // do something
    }
    console.log(i); // 10
    
    // 当循环结束的时候,其实我们是希望变量 i 可以被销毁的。
    // 但其实它被留在了全局

这个时候,我们使用 let 来声明循环中的变量,就可以轻易的解决这个问题。

    for (let i = 0; i < 10; i++) {
        // do something
    }
    console.log(i); // ReferenceError: i is not defined
    
    // 可以看到,循环结束,变量 i 就被销毁了。 perfect~~

最后总结一下,letconst 帮助我们解决了不少问题,我们不会再为变量提升引发的种种问题而困惑了,同时在循环中使用 let 来代替 var 可以在循环结束的时候销毁变量,避免无用的变量影响全局。而当前使用块级绑定的最佳实践是:默认使用 const ,只在确定需要改变变量的值时,使用 let ,以最大化地避免错误的产生。

如果文章中有错误或表述不严谨的地方,欢迎指正。

也欢迎大家关注我的同名微信公众号:李等等扣丁

相关文章

  • 《深入理解ES6》学习笔记(第三天)

    《深入理解ES6》学习笔记(第三天) 第一章 块级作用域绑定 第2节 块级声明块级声明用于声明在指定块的作用域之外...

  • js 作用域链 和 原型链

    作用域链 js拥有全局作用域(window)、函数作用域、块级作用域(es6)。块级作用域是es6开始才拥有的,因...

  • JS基础知识(2) -- 作用域和作用域链

    作用域 作用域就是变量与函数的可访问范围 全局作用域 函数作用域 ES6块级作用域 ES5没有块级作用域,ES6有...

  • js 作用域

    js 作用域主要有:全局作用域和局部作用域,es5之前没有块级作用域,es6有了块级作用域 何为块级作用域,块级作...

  • let 和 const

    一、JS中的块级作用域 ES6之前JS不支持块级作用域在ES6之前,JS是没有块级作用域这个概念的,只有全局作用域...

  • 重读《深入理解ES6》—— 块级作用域

    一、关于变量声明提升 在 ES5 中,我们通常会使用 var 来声明变量。在使用 var 声明变量的时候,通常会遇...

  • ES6分享会总结

    学到的内容 ES6的块级作用域 1. 块级作用域的概念 2. ES6允许在块级作用域内声明函数 3. 函数在块级作...

  • 你真的懂let和const吗?

    块级作用域 在ES6之前我们脑海里应该只存在全局作用域和函数级作用域,没有块级作用域。那么为什么要引入块级作用域呢...

  • 《深入理解ES6》学习笔记(第四天)

    《深入理解ES6》学习笔记(第四天)第一章 块级作用域绑定 第2节 块级声明 2.1 cont声明 使用const...

  • ES6语法--let和const

    1:let和const:作用域,全局作用域,函数作用域以及块级作用域(es6)。 let声明的变量只在块级作用域内...

网友评论

    本文标题:重读《深入理解ES6》—— 块级作用域

    本文链接:https://www.haomeiwen.com/subject/sdkzuqtx.html