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

栏目: JavaScript · 发布时间: 5年前

内容简介:在 ES5 中,我们通常会使用事实上,无论在全局作用域或者函数作用域中,只要通过其实,变量提升的机制,不太符合我们的编码习惯,我们常常希望代码能够按照顺序执行,这也符合一般人的逻辑习惯。为此 ES6 引入了块级作用域的概念。

在 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》 —— 块级作用域

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning ARKit for iPhone and iPad

Beginning ARKit for iPhone and iPad

Wallace Wang / Apress / 2018-11-5 / USD 39.99

Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具