ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现.
let命令
ES6新增了let
命令,用来声明变量。
特点:
1)它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
{
let a=10;
var b=20;
console.log(a,b);// 10 20
}
console.log(b);//20
console.log(a);//a is not defined
在for循环中,就很适合let命令
for (let i = 0; i < 10; i++) {}
console.log(i);//i is not defined
在上面的代码中,计数器i是使用let声明的,所以只在for循环体中有效,在循环体以外引用就会报错.
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);//--》 10
};
}
a[6]();
上面代码中,变量i
是var
声明的,在全局范围内都有效。所以每一次循环,新的i
值都会覆盖旧值,导致最后输出的是最后一轮的i
的值。
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是4。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);//4
};
}
a[4]();
Let实际上为Javascript新增了块级作用域。外层作用域无法读取内层作用域的变量,内层作用域可以定义外层作用域的同名变量。
下面的函数有两个代码块,都声明了变量n
,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var
定义变量n
,最后输出的值就是10。
function f1() {
let n = 5;
if (true) {
let n = 10;// 函数内部let声明n=10 打印时不在作用域内
}
console.log(n); // 5
}
2)不存在变量的提升
let
不像var
那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。
console.log(foo); // 输出undefined
console.log(bar); // 报错Identifier 'bar' has already been declared
var foo = 2;
let bar = 2;
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚本开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。变量bar
用let
命令声明,不会发生变量提升。这表示在声明它之前,变量bar
是不存在的,这时如果用到它,就会抛出一个错误。
3)暂时性死区,避免全局变量的污染
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。所以变量一般要在声明后进行使用,否则会出现报错。
var tmp =123;//全局变量
if (true) {
// TDZ开始
tmp = 'abc'; // 报错ReferenceError
console.log(tmp); //报错 ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined 没有赋值
tmp = 123;
console.log(tmp); // 123
}
有些死区比较隐蔽,不容易被发现
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
上面代码中,调用bar
函数之所以报错(某些实现可能不报错),是因为参数x
默认值等于另一个参数y
,而此时y
还没有声明,属于”死区“。如果y
的默认值是x
,就不会报错,因为此时x
已经声明了。
function bar(x = 2, y = x) {
return [x, y];
}
bar(); // [2, 2]
4)不允许重复声明
var a=10
var a=20
console.log(a)//20
let b=1
b=2
console.log(b)//2
let c=3
let c=4
console.log(c)//报错
{
let d=5
}
let d=3
console.log(d)//3
const命令
const
声明一个只读的常量。一旦声明,常量的值就不能改变
特点:
1)const 具备 let所具备的一切特性
2)声明之后不可以重新赋值
3)声明的同时必须初始化
{
const a=1
}
console.log(a) //报错,只在声明所在的块级作用域内有效
const b=2
b=3
console.log(b)//不可以重新赋值
const c
console.log(c)//报错 只声明没有初始化
const obj = {
name:"tom",
age:12
}
obj.age =14 // 常量obj中存储的是一个地址,这个地址指向了age对象,地址是不能改变指向的,但对象本身是可变的,所以可以向其添加属性,或者改变值
console.log(obj) //--》{name:'tom' age:14}