zoukankan      html  css  js  c++  java
  • var/let/const区别何在??(转载)

    原文地址:http://www.cnblogs.com/liuhe688/p/5845561.html

    let和const有很多相似之处,先说一说let吧。

    1. let添加了块级作用域

    我们知道,JavaScript是没有块级作用域的,如果在块内使用var声明一个变量,它在代码块外面仍旧是可见的:

    if (true) {
         var foo = 3;
    }
    console.log(foo);    // 3
    
    for (var i = 0; i < 9; i++) {
         var j = i;
    }
    console.log(i);      // 9
    console.log(j);      // 8

    可以看到,在上面代码中,我们虽然是在块内声明的变量,但代码块执行完毕后,依然可以访问到相应的变量,说明JavaScript中没有块级作用域的。

    而ES6规范给开发者带来了块级作用域,如果把var换成let命令,我们就可以获得一个块级变量:

    if (true) {
         let foo = 3;
    }
    console.log(foo);   // Uncaught ReferenceError
    
    for (let i = 0; i < 9; i++) {
         let j = i;
    }
    console.log(i);     // Uncaught ReferenceError
    console.log(j);     // Uncaught ReferenceError

    从上面代码可以看出,块内声明的变量,块外是不可见的,如果试图引用一个块内用let声明的变量,就会引发一个异常。

    2. let约束了变量提升

    在JavaScript中,变量提升是很常见的,例如下面这段代码:

    function hoistVariable() {
        console.log('foo:', foo); // foo: undefined
        var foo = 3;
    }
    
    hoistVariable();

    在代码正式执行之前,编译器将会对代码进行预编译分析阶段,在这个阶段,当前作用域中的变量和函数,将被提升到作用域的顶部。(注:目前的JavaScript引擎大都对源代码进行了编译处理,并且预编译和提升是抽象出来的概念。)

    经过预编译之后的代码逻辑如下所示:

    function hoistVariable() {
        var foo;
        console.log('foo:', foo); // foo: undefined
        foo = 3;
    }
    
    hoistVariable();

    ES6中的let命令规范了变量的声明,约束了变量提升,也就是说,我们必须先声明,然后才可以使用,下面者段代码将会报错:

    function nonHoistingFunc() {
        console.log('foo:', foo); // Uncaught ReferenceError
        let foo = 3;
    }
    
    nonHoistingFunc();

    正确的使用方式是,永远将变量声明置于当前作用域顶部:

    function nonHoistingFunc() {
        let foo = 3;
        console.log('foo:', foo); // 3
    }
    
    nonHoistingFunc();

    需要注意的是,不管是var还是let,预编译过程中,都发生了变量提升,但与var不同的是,ES6对let进行了约束,其规定,在真正的词法变量声明之前,以任何方式访问let变量都是不允许的,所以从开发人员角度来看,let禁止了变量提升这一行为。

    关于这一点,大家可以参考ES6规范中“let和const变量的声明”。

    3. let有暂时性死区

    只要在块内存在let命令,那么这个变量就绑定到了当前块作用域,不再受外部变量的影响,下面代码将会引发一个错误:

    var foo = 3;
    
    if (true) {
        foo = 5; // Uncaught ReferenceError
        let foo;
    }

    ES6规定如果块内存在let命令,那么这个块就会成为一个封闭的作用域,并要求let变量先声明才能使用,如果在声明之前就开始使用,它并不会引用外部的变量。

    如果把这里的let替换成var,由于不会形成块级作用域,变量的声明其实是与第一行重复了,相当于下面这段代码:

    var foo;
    
    foo= 3;
    
    if (true) {
        foo = 5;
    }

    4. let禁止重复声明变量

    如上面所述,使用var可以重复声明变量,但let不允许在相同作用域内重复声明同一个变量,下面的代码会引发错误:

    // SyntaxError
    function func() {
        let foo = 3;
        var foo = 5;
    }
    
    // SyntaxError
    function func() {
        let foo = 3;
        let foo = 5;
    }
    
    // SyntaxError
    function func(arg) {
        let arg;
    }

    5. let不会成为全局对象的属性

    我们在全局范围内使用var声明一个变量时,这个变量会自动成为全局对象的属性(在浏览器和Node.js环境下,这个全局对象分别是window和global),但let是独立存在的变量,不会成为全局对象的属性:

    var a = 3;
    console.log(window.a); // 3
    
    let b = 5;
    console.log(window.b); // undefined

    6. 最后:const命令

    以上let所介绍的规则均适用于const命令,不同的是,const声明的变量不能重新赋值,也是由于这个规则,const变量声明时必须初始化,不能留到以后赋值,所以下面的代码是不合法的:

    const a = 3;
    
    a = 5;   // Uncaught TypeError: Assignment to constant variable
    
    const b; // Uncaught SyntaxError: Missing initializer in const declaration

    以上就是let和const的内容,可以看出,let和const大大改进了ES5的变量机制,使得JS更严谨和规范,随着ES6支持程度的提高,我们应该开始习惯let和const的使用了。

  • 相关阅读:
    【贪心】【堆】Gym
    【并查集】Gym
    【拓扑排序】【bitset】Gym
    【递归】【线段树】【堆】AtCoder Regular Contest 080 E
    【二分图】【并查集】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem L. Canonical duel
    【动态规划】【滚动数组】【bitset】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem J. Terminal
    【二分】【字符串哈希】【二分图最大匹配】【最大流】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem I. Minimum Prefix
    【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game
    【推导】【构造】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem E. Space Tourists
    【推导】【贪心】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem D. Clones and Treasures
  • 原文地址:https://www.cnblogs.com/LLLLily/p/7389652.html
Copyright © 2011-2022 走看看