美文网首页
新的声明方式

新的声明方式

作者: 名字太短感觉不爽 | 来源:发表于2019-01-06 16:40 被阅读0次

    新的声明方式

    之所以会提出新的变量声明方式,在我看来一是因为之前仅有的var声明方式过于单一,无法满足对变量的多样化的声明需求,二就是var声明的变量在绑定作用域时过于粗暴。
    探讨三个问题:一个是变量提升机制,一个是全局作用域的绑定,还有一个是如何声明局部变量和常量。


    问题一:变量提升机制

    看一个经典的例子:

    function test(flag) {
        if(flag) {
            var value = 1;
        } else {
            return null;
        }
    }
    

    我们的本意是希望在flag为false时不声明变量value,但实际情况是value的声明会提升到test函数的顶部,而flag只能控制是否对value赋值。相当于如下所示:

    function test(flag) {
        var value;    // value被提升到函数顶部
        if(flag) {
            value = 1;
        } else {
            return null;
        }
    }
    

    这就是变量提升机制。


    问题二:全局作用域的绑定

    我们在全局作用域下执行如下代码:

    var a = 1;
    function b() {};
    window.a;    // 1
    window.b;    // ƒ b() {}
    

    我们会发现,全局变量a和函数b自动挂在window下。这种特性会导致属性误覆盖。那么怎么解决这个问题呢?ES5常用的方式就是闭包。其实闭包最大的用处就是处理作用域的问题,这都是因为JS的作用域比较晦涩难懂有比较混乱导致的。


    问题三:声明局部变量和常量

    在ES5中,如果我们想要声明一个局部变量,最常见的就是把这个局部作为一个函数,在函数内部声明的变量自然就是这个函数的局部变量。如下所示:

    function test() {
        var a = 1;
    }
    console.log(a); // Uncaught ReferenceError: a is not defined
    

    那么如果想要声明一个常量呢?直接使用var是不行的,这也是我上面提到的不够多样的缺点。如果你想要一个变量被赋值后无法更改,可以借助对象,将这个变量声明为对象的一个属性,然后借助Object.defineProperty方法,禁止更新这个属性的值。还有一种方式就是利用闭包,将这个变量放在一个闭包里,然后只对外暴露set和get方法。这两种方式都是比较曲折的方法。


    以上三个问题都是为什么ES6要新增新的声明方式的原因之一。
    ES6新增了let和const两种声明方式,解决了我上面提到的问题。这里说两个新声明方式比较强大的两个特性:

    特性一:临时死区实现更清晰的块作用域

    我们把问题一中的变量声明方式如果替换为let或者const会怎么样?

    function test(flag) {
        if(flag) {
            let value = 1;
        } else {
            return null;
        }
        return value;
    }
    test(true);    // Uncaught ReferenceError: value is not defined
    

    使用let,value就不会存在变量提升机制,而是放入了一个叫做临时死区(TDZ)中,如果我们在value声明前调用value,就会报错。所以上述代码中的value,只有在flag为true,并且只有在if条件内才能调用。在test中也无法调用value。改成const也是一样的。


    特性二:常量的便捷声明

    喜大普奔,我们再也不需要拐弯抹角的去声明一个类似常量的变量。而是直接通过const,就可以声明一个常量。这里有一个需要注意的点,const在声明一个对象类型的值时,“不可更改性”体现在我们不能改变这个常量的指向,也就是说从头到尾只能指向一个对象,如下所示:

    const a = {};
    a = {};    // Uncaught TypeError: Assignment to constant variable.
    

    但是允许修改这个对象的内容。这是比较特殊的一点。之所以会有这种特点,是和这个常量是存储值还是存储地址相关的。

    相关文章

      网友评论

          本文标题:新的声明方式

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