一、ES6 简介
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言
ES6 是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等;而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准
二、ES6 转码
Node 是 JavaScript 的服务器运行环境(runtime),它对 ES6 的支持度更高,但有些执行环境不能完全支持 ES6 语法
ES6 转码器 可以将 ES6 代码转为 ES5 代码,从而在现有环境执行。
三、ES6 新特性汇总(待更新)
- 增加块级作用域
四、变量的 声明
1. 块级作用域
ES6的块级作用域,是通过
let
、const
声明变量,来体现的只要一个代码块
{ }
中存在let
、const
,就形成了一个封闭的作用域(块级作用域);每一个{ }
都是一层块级作用域块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
2. let 、const 声明变量,详解
(1)通过 let
、 const
声明的变量,不是全局变量, 不能通过 window 访问
- 只能在当前块级作用域 及 子作用域内能够被访问到
(2)let
声明变量,允许被修改
(3)const
声明一个只读的常量,不允许被修改
- 意味着:
const
一旦声明变量,就必须立即初始化,不能留到以后赋值
const foo; // SyntaxError: Missing initializer in const declaration
- 本质:并不是变量的值不得改动,而是变量指向的那个内存地址不得改动;
简单数据类型:值就保存在变量指向的那个内存地址,所以不能有任何改变
复杂数据类型:
const
声明的变量 指向内存地址,const
只能约束 指针指向的内存地址不变;不能约束 内存地址中 的数据结构
// 所以:const 声明复杂数据类型,其数据结构是可变的
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
ondole.log(foo.prop); // 123
3. let 、const 声明变量,不存在变量提升
let
、const
声明变量,不存在变量提升
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
4. let 、const 声明变量,造成暂时性死区(TDZ)
let
、const
声明变量,不允许 在变量声明之前 使用,造成暂时性死区let
、const
声明变量,形成块级作用域,在声明变量之前的区域,都是 变量的死区(不允许 使用变量,使用会报错)
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
}
// 上面代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”
- 比较隐蔽的死区
function bar(x = y, y = 2) {
return [x, y];
}
console.log(bar()); // 报错
5. let 、const 声明变量,不允许重复声明
- 对比:var 声明的变量,重复声明 无效,不会报错
if (true) {
const a = 10;
const a = 1;
}
- 函数直接作用域内 使用
let
重新声明形参,会报错
function func(arg) {
let arg; // 报错
}
- 内层作用域可以定义外层作用域的同名变量
function func(arg) {
{
let arg; // 不报错
}
}
6. let 、 const 声明的全局变量,不属于顶层对象的属性
ES5 败笔之一:顶层对象的属性与全局变量是等价的;很容易不知不觉的创建多个全局变量,读写困难,维护困难
- ES6 规定:
var命令和function命令声明的全局变量,依旧是顶层对象的属性
let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性
var a = 1;
console.log(window.a); // 1
let b = 1;
console.log(window.b); // undefined
五、变量的 解构赋值
1. 概念
- ES6 允许按照一定模式,从数组 和 对象中提取值,对变量进行赋值,这被称为解构赋值(Destructuring)
2. 解构赋值 --- 数组
模式匹配 内部机制:数组的元素是按次序排列的,相同位置 数据结构相同,才能成功的解构赋值
分为:存在完全结构赋值,和不完全结构赋值
// 完全结构赋值
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo); // 1
console.log(bar); // 2
console.log(baz); // 3
// 不完全结构赋值
let [x, y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 2
// `...a` 代表定义数组
let arr = [1, 2, 3, 4];
let [a, b, ...c] = arr;
console.log(c); // [3, 4]
- 结构赋值 数组的长度(因为数组 有
length
属性)
let arr = [1, 2, 3];
let {length: leg} = arr;
console.log(leg); // 3
2. 解构赋值 --- 对象
- 模式匹配 内部机制:先在已有对象中找到同名属性,然后再将已有对象中同名属性的值 赋给 定义变量的属性值
// 定义的变量名 与 属性名一致
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
// 定义的变量名 与 属性名不一致
let { foo: baz } = { foo: ‘aaa‘, bar: ‘bbb‘ };
console.log(baz); // "aaa"
3. 解构赋值 --- 指定默认值
- 默认值生效的条件是,数组 / 对象 的属性值 严格等于
undefined
let [x = 1] = [undefined];
console.log(x); // 1
let [y = 1] = [null];
console.log(y); // null
- 如果默认值是一个表达式,那么这个表达式是惰性求值的(只有在用到的时候,才会求值)
function f() {
console.log(‘aaa‘);
}
let [x = f()] = [1]; // 无输出
let [x = f()] = []; // aaa
- 默认值可以引用解构赋值的其他变量,但该变量必须已经声
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError
4. 解构赋值 --- 函数 参数
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
5. 解构赋值 的用途
交换变量
let x = 1;
let y = 2;
[x, y] = [y, x];
函数 设置默认参数
function(n = 1) {
return n;
}
函数 参数为对象 设置默认值
function foo({
x = 10,
y = 5
}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo() // TypeError: Cannot read property ‘x‘ of undefined
function foo({
x = 10,
y = 5
} = {}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo() // 1 5
提取 对象 / json 中的数据
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]