1.let
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
{
let a = 10;
var b = 10;
}
console.log(a);//a is not defined
console.log(b);//10
所以在for循环中,用let声明的变量只在for循环体内有效,在循环体外就会报错。
for (let i =0;i<5;i++){
console.log(i);
}
console.log(i); //i is not defined
for (var j =0;j<5;j++){
console.log(j);
}
console.log(j);//5
不存在变量提升:
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错
let bar = 2;
上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。
暂时性死区:
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
typeof x; // ReferenceError
let x;
typeof y;//不会报错
上面代码中,变量x使用let命令声明,所以在声明之前,都属于x的“死区”,只要用到该变量就会报错。作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。
隐蔽的死区:
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了。
// 不报错
var x = x;
// 报错
let x = x;
在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。
不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
ES5中只有全局作用域和函数作用域,没有块级作用域;所以可能会造成内层变量会覆盖外层变量或者用来计数的循环变量泄露为全局变量的情况。
let为js新增了块级作用域。
2.const
- const声明一个只读的变量,一旦声明,常量的值就不能更改。所以,一旦声明,就必须立即赋值,否则报错。
- const作用域与let相同,只在声明所在的块级作用域内有效。
- const声明的变量也不提升,存在暂时性死区,只能在声明的位置后面使用。
- const声明的变量也不可重复声明。
本质:const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址(栈),因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址(堆)),至于它指向的数据结构是不是可变的,就完全不能控制了。
因此,如果const
声明的是一个引用数据类型的数据,可以通过修改这个数据本身的属性来更改数据。
例如:
const arr1 = [10,20];
console.log(arr1 = [10,20,30]); // Uncaught TypeError: Assignment to constant variable
console.log(arr1.push(30)) // (3) [10, 20, 30]
3.ES6声明变量的六种方法
ES5 只有两种声明变量的方法:var
命令和function
命令。ES6 除了添加let
和const
命令,另外两种声明变量的方法:import
命令和class
命令。所以,ES6 一共有 6 种声明变量的方法。
网友评论