ECMAScript是ECMA International定义的商标脚本语言规范。 创建它是为了标准化JavaScript。ES脚本语言具有许多实现,流行的实现是JavaScript。ECMAScript标准的第六版是ES6或ECMAScript6
1、let与const
- let
(1).基本用法
ES6 新增了let命令,用来声明变量。类似于var,但是所声明的变量,只在let命令所在的代码块内有效
{
let a = 10;
var b = 1;
}
a; // ReferenceError: a is not defined.
b; // 1
(2).不能重复声明
let 不允许在相同作用域内,重复声明同一个变量
function func() {
var a = 10;
let a = 1;
}
func(); //Identifier 'a' has already been declared
function func() {
let a = 10;
let a = 1;
}
func(); //Identifier 'a' has already been declared
(3).不存在变量提升
var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined。 let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则会报错
console.log(foo); //undefined
var foo = 2;
console.log(bar); // ReferenceError:Cannot access 'bar' before initialization
let bar = 2;
(4).暂时性死区
ES6规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前使用这些变量,就会报错。这在语法上称为 “暂时性死区”
var tmp = 123;
if (true) {
tmp = "abc"; // ReferenceError:Cannot access 'tmp' before initialization
let tmp;
}
Tips: “暂时性死区”的本质就是:只要一进入当前作用域,所要使用的变量就已经存在了,但不可获取(否则报错),只有等到声明的那一行代码出现,才可以获取和使用
- const
const命令的用法和let相似,最大不同点就是:const声明一个只读的常量。一旦声明,常量的值就不能改变
Tips:这个不可改变的是指针,所以对于const声明的对象和数组还是可以改变的
2、 变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
1、数组的解构赋值
(1)基本用法
// 之前,为变量赋值,可以直接指定值
let a = 1;
let b = 2;
let c = 3;
// ES6中允许这样
let [a, b, c] = [1, 2, 3]; // 可以从数组中提取值,按照对应位置,对变量赋值。
//也可以使用嵌套数组的方式进行解构
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo; // 1
bar; // 2
baz; // 3
let [, , third] = ["foo", "bar", "baz"];
third; // "baz"
(2)默认值
解构赋值允许指定默认值
let [foo = true] = [];
foo; // true
let [x, y = "b"] = ["a"];
x; //'a'
y; //'b'
默认值可以引用解构赋值的其他变量,但该变量必须已经声明
let [x = y, y = 1] = []; // ReferenceError: y is not defined -- let的暂时性死区
let [x = 1, y = x] = [1, 2];
2、对象的解构赋值
(1)基本用法
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo; // "aaa"
bar; // "bbb"
let { baz } = { foo: "aaa", bar: "bbb" };
baz; // undefined
对象的解构与数组的解构,一个重要的不同点在于: 数组元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量名与属性同名,才能取到正确的值。
如果没有与变量名对应的属性名,导致取不到值,最后等于undefined
Tips:变量名和属性名不一样
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量
(2)默认值
对象的解构也可以指定默认值。默认值生效的条件是对象的属性值严格等于 undefined
let {x, y = 5} = {x: 1};
x;// 1
y;// 5
Tips:已经声明的变量用于解构赋值需要注意
let x;
{x} = {x:1};
//会报错,JavaScript引擎会将 {x} 理解为一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。
//正确的写法,将需要解构的部分用括号()包起来
let x;
({x} = {x:1}); //1
3、字符串解构赋值
字符串也可以解构赋值,被转换成了一个类似数组的对象
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
4、数值和布尔值解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转化为对象
let { toString: s } = 123;
s === Number.prototype.toString; // true
let { toString: s } = true;
s === Boolean.prototype.toString; // true
解构赋值的规则是:只要等号右边的值不是对象或数组,就先将其转化为对象。 由于 undefined 和 null 无法转化为对象,所以对他们进行解构赋值都会报错
5、 函数参数的解构赋值
function add([x, y]) {
return x + y;
}
add([1, 2]); // 3
[[1, 2],[3, 4],].map(([a, b]) => a + b);
// [ 3, 7 ]
函数 add 的参数看似是一个数组,但在传入参数时,数组参数就解构为变量 x 和 y。对于函数内部代码来说,参数就是 x 和 y
Tips:函数参数的解构也可以使用默认参数,如下:
function decon({ x = 0, y = 0 } = {}) {
return [x, y];
}
decon({ x: 3, y: 8 }); // [3, 8]
decon({ x: 3 }); // [3, 0]
decon({}); // [0, 0]
decon(); // [0, 0]
函数 decon 的参数是一个对象,通过对这个对象进行解构,得到变量 x 和 y 的值。如果解构失败,x 和 y 等于默认值
Tips:还有一种指定默认值的写法:
function decon({ x, y } = { x: 0, y: 0 }) {
return [x, y];
}
decon({ x: 3, y: 8 }); // [3, 8]
decon({ x: 3 }); // [3, undefined]
decon({}); // [undefined, undefined]
decon(); // [0, 0]
为函数 decon 的参数指定默认值,而不是为变量 x 和 y 指定默认值