今天学习了es6中的let和const命令,借此整理一下笔记。
let :
let 和 var 的声明方式一样,但有 var 比不上的优点。下面用 var 和 let 的例子来加深对 let 的理解。
1 let 只作用与当前作用域中
在声明var时,在无特别情况下,代码块里的var外部也可以访问到的,但是let声明之后,外部是访问不到的,会报错。
{ var a = 123 let b = 456 } console.log(a) // 123 console.log(b) // ReferenceError: b is not defined
以前面试经常出现的一道题,下面会打印出什么
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[5]();
结果是 10 ,这就是 var i 没有指定块级作用域,指向了全局。变量i
是var
命令声明的,在全局范围内都有效,所以全局只有一个变量i
。每一次循环,变量i
的值都会发生改变,而循环内被赋给数组a
的函数内部的console.log(i)
,里面的i
指向的就是全局的i,
数组a
的成员里面的i
,指向的都是同一个i
,导致运行时输出的是最后一轮的i
的值,也就是 10。
如果使用let,利用它的具有块级作用域的特性,我们可以获取数组a[5]的值。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[5](); // 5
为何是5,而不是10 了,因为变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是5。
另外 let 为javascript添加了块级作用域,使声明的变量只作用与当前的代码块。
function fn() {
let n = 1;
if (true) {
let n = 2;
console.log(n) // 2
}
console.log(n) // 1
}
fn()
而 var 则不会,因为根据var变量声明的原则,if代码块的n重复使用,后面的覆盖前面的。
function fn() {
var n = 1;
if (true) {
var n = 2;
console.log(n) // 2
}
console.log(n); // 2
}
fn()
2 let 不存在变量提升
var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。这是javascript在预编译过程中,把var声明的变量提升到当前作用域的最上端,变量的值不变。但是let不存在变量提升,如果未声明就使用或者声明在使用之后会报错 ReferenceError。
console.log(a) var a = 1 // undefined console.log(b) let b = 2 // Uncaught ReferenceError: b is not defined
3 let 具有暂时性死区
{ a = 123 b = 456 let a var b console.log(a) // Uncaught ReferenceError: a is not defined console.log(b) // 456 }
上面的例子的情况就是说明了let的暂时性死区,let a在使用之后,触发了暂时性死区,就报错。而var因为在声明时发生变量提升提到最顶端,所以能打印出456。
4 let 不允许重复变量
{ let a = 1 let a = 2 // Uncaught SyntaxError: Identifier 'a' has already been declared }
{ var a = 1 // Uncaught SyntaxError: Identifier 'a' has already been declared let a = 2 }
5 let 使变量不再是默认的全局变量。
var a = 1 console.log(window.a) // 1 let b = 2 console.log(window.b) // undefined
const:
const 声明一个只读的常量。一旦声明,常量的值就不能改变。
const a = 1 a = 2 // Uncaught TypeError: Assignment to constant variable. console.log(a)
其本质就是:const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const 的特点和 let 的一样:
1 只作用与当前的块级作用域
2 不存在变量提升
3 也存在暂时性死区
4 不允许重复声明同一个变量
5 使变量不再是全局属性
ps:const 的本质:不是变量的值不得改动,而是变量指向的那个内存地址不得改动。
const a = 'string' a = 'String' // Uncaught TypeError: Assignment to constant variable. console.log(a) const b = { name: 'peter' } b.name = 'Bob' console.log(b) // {name: "Bob"} b = {} //error console.log(b)
a 是字符串,值就保存在地址,不可变,一变就报错
b 是个对象,对象保存的是个地址,是个指针,只要地址不变,里面的内容可以捣鼓,但是如果要把这个对象b初始化等等就相当于改变了地址。
参考资料:
阮一峰大大的es6: http://es6.ruanyifeng.com