阅读 103

let和const

ES6 新增了let命令,所声明的变量,只在let命令所在的代码块内有效。

关于let的要点

1.使用let的for循环的特别之处:

设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。举例!

        for (let i = 0; i < 3; i++) {             let i = "abc"             console.log(i);         }         //结果打印三次abc 复制代码

函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域(同一个作用域不可使用 let 重复声明同一个变量)。

2. 不存在变量提升

var不一样它所声明的变量一定要在声明后使用,否则报错。

3. 暂时性死区

如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。举例!

        var tmp = 123;         if (true) {             tmp = "abc" //ReferenceError             let tmp         } 复制代码

包括这种情况:

        let x = x //ReferenceError 复制代码

因为js是先取值再赋值,先RHS查询取得x的值然后LHS查询赋值给变量x,然而x的值并没有被声明,所以报错+

4.不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。举例!

        function fn(){             let a = 10             var a = 20 //Uncaught SyntaxError: Identifier 'a' has already been declared         } 复制代码

因此,不能在函数内部重新声明参数。

关于块作用域

es5只有全局作用域和函数作用域,没有块级作用域,就会出现这样的情况:

       var tmp = new Date()        function fn(){            console.log(tmp);            if(false){                var tmp = "hello world"            }        }        fn() // undefined 复制代码

这是由于变量提升导致的,if语句内的var tmp被提升到了函数fn中第一行

        function fn() {             var tmp             console.log(tmp); // undefined             if (false) {                 tmp = "hello world"             }         } 复制代码

let实际上为 JavaScript 新增了块级作用域。

        function fn() {             let a = 5;             if (true) {                 let a = 10             }             console.log(a);         }         fn() // 5 复制代码

两个let创建的两个块作用域,两个a都是独立的互不干扰,原先匿名函数的的作用也被取代了

        //匿名函数写法         (function () {             var a = 10         }())         //块级作用域写法         {             let a = 10         } 复制代码

块级作用域与函数声明

ES5规定函数只能在全局作用域和函数作用域之中声明,不能在块级作用域声明。但ES6允许在块级作用域之中声明函数,函数声明语句的行为类似于let,在块级作用域之外不可引用。关于这一点,不同的支持环境会导致不同的结果,应该避免在块级作用域内声明函数。

顺便一提,ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

关于const命令

const声明一个只读的常量。一旦声明,常量的值就不能改变。

        const PI=3.1415         PI=3 // Uncaught TypeError: Assignment to constant variable 复制代码

这也意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。举例!

        const PI; // Uncaught SyntaxError: Missing initializer in const declaration 复制代码

const的作用域与let命令相同:只在声明所在的块级作用域内有效。

        {const PI=3.1415}         console.log(PI); //Uncaught ReferenceError: PI is not defined 复制代码

同样的,const命令声明的常量也是不进行提升,同样存在暂时性死区,只能在声明的位置后面使用,也与let一样不可重复声明。

const本质

const实际上保证的,并不是变量的值不得改动,而是变量指向的内存地址不得改动。因此对于复杂类型的数据,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。举例!

        const foo = {}         foo.name = "哈哈" // 哈哈         console.log(foo.name);         foo = {} // Uncaught TypeError: Assignment to constant variable. 复制代码

foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,但对象本身是可变的,所以依然可以为其添加新属性。

顺便一提:let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。(在浏览器中顶层对象就是window)

本文参考自《ES6入门标准》一书


作者:砂糖小刀
链接:https://juejin.cn/post/7022545026064334861

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐