先奉上一张ES6的思维导图,简单版的,只是总结了常用的 API,下面文字部分也都是总结一些 ES6 常用的语法及知识点,不过感觉一些常用的 API 在我们开发中也够用了。详细的解释可以去看阮一峰老师的 ECMAScript 6 入门

可以转载本图,但是希望可以注明出处,谢谢。
OK,跟着我一起开始文字和代码的实践吧。
一、 let 和 const
1.1 let
let声明变量时不允许重复声明。
let a = 'test';
let a = 'test2'; // 报错
let声明变量会生成独立的块级作用域,外层作用域拿不到内层声明的变量
例子:
{
{
let insane = 'Hello World';
}
console.log(insane); // 报错
}
在let定义之前使用,是获取不到变量的,let定义的变量会存在暂时性死区。
1.2 const
const声明一个只读的变量,一旦声明,常量的值就不能改变,其实不能改的是变量指向的地址。
const PI = 3.1415;
console.log(PI); // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const声明变量,初始化变量时必须立即赋值,不能留着以后赋值,否则会报错。
const foo;
// SyntaxError: Missing initializer in const declaration
const类似let,同样存在块级作用域,只有在指定的作用域内使用才会有效。
if (true) {
const MAX = 5;
}
MAX; // Uncaught ReferenceError: MAX is not defined
const声明的变量不会提升,存在暂时性死区,只有在声明位置之后才能使用。在声明之前使用会报错,如下面的例子。
if (true) {
console.log(HELLO); // ReferenceError
const HELLO = 5;
}
const声明的变量同样不能重复声明
var message = 'Hello!';
let age = 25;
// 以下两行都会报错
const message = 'Goodbye!';
const age = 30;
const的本质其实并不是变量的值不可以改动,而是变量指向的内存地址所保存的数据不能改变,对于简单类型的数据(数值,字符串,布尔值),值就会保存到指定的内存地址,其实内存地址等同于变量本身。但是对于复合类型的数据(数组,对象),变量指向的是内存地址,所以对象内的值是可以改变的,但是对象本身是不能改变的。
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop; // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
1.3 注意点
let和const定义的变量和var不同,var定义的变量在 window 下可以访问,但是let和const定义的变量在 window 下是不能访问的
var a = 'a';
let b = 'b';
const c = 'c';
window.a; // a
window.b; // undefined
window.c; // undefined
二、 解构赋值
2.1 基本用法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值。按照“模式匹配“的写法,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
如果结构不成功,变量的值就等于undefined
let [a, b, c] = [1, 2, 3];
a; // 1
b; // 2
c; // 3
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo; // 1
bar; // 2
baz; // 3
let [, , third] = ['foo', 'bar', 'baz'];
third; // "baz"
let [x, , y] = [1, 2, 3];
x; // 1
y; // 3
let [head, ...tail] = [1, 2, 3, 4];
head; // 1
tail; // [2, 3, 4]
let [x, y, ...z] = ['a'];
x; // "a"
y; // undefined
z; // []
如果左右两边的模式是不同的,那就会导致报错
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
2.2 默认值
解构赋值允许指定默认值。
let [foo = true] = [];
foo; // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
ES6 内部使用严格相等运算符===,判断一个位置是否有值,只有当一个数组成员严格等于undefined,默认值才会生效。
let [x = 1] = [undefined];
x; // 1
let [x = 1] = [null];
x; // null
如果一个数组成员是null,默认值就不会生效,因为null在严格模式下不等于undefined。
默认值可以引用解构赋值的其他变量,但是该变量必须已经声明。
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: y is not defined
2.3 对象的解构赋值
对象的解构赋值和数组的有些不同。数组的元素必须按照次序排列,变量的取值取决于他们的位置;但是对象的解构赋值,变量不需要按照次序,只需要变量与属性同名,才能取到正确的值。
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' };
baz; // "aaa"
foo; // error: foo is not defined
其实foo是匹配的模式,baz才是真正的变量,被赋值的变量是baz,而不是foo,foo是用作去找属性的属性名。
在 ES6 中对象的属性名和属性值如果相同可以进行简写
{foo: foo} 可以写成 {foo},所以实际上,对象的解构赋值进行了简写。
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
2.4 字符串的解构赋值
字符串在解构赋值时,会将字符串转换成一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a; // "h"
b; // "e"
c; // "l"
d; // "l"
e; // "o"
2.5 数值和布尔值的解构赋值
解构赋值时会将右边的数值和布尔值转换成对象。
let { toString: s } = 123;
s === Number.prototype.toString; // true
let { toString: s } = true;
s === Boolean.prototype.toString; // true
解构赋值的规则是,只要等号右边的值不是数组或者对象,就先转换成对象,undefined 和 null 无法转换成对象,所以无法解构赋值。
2.6 用途
说了这么多,说说解构赋值的用途吧。其实解构赋值的用途有很多。
- 交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
- 从函数返回多个值
函数返回值只能是一个,可以将对象或者数组返回,然后利用解构赋值取出这些值
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
- 函数参数的定义
解构赋值能方便的奖传入的参数和变量名对应起来。
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
- 提取 JSON 数据
解构赋值对提取 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]
- 输入模块的指定方法
加载模块时,可以引用指定的方法,解构赋值使得输入的语句非常清晰
const { SourceMapConsumer, SourceNode } = require('source-map');
三、 多行字符串和模板变量
方便了很多,不需要在拼接字符串的时候换行使用加号拼接
let name = 'shi';
let age = 20;
let html = `<div>
<p>${name}</p>
<p>${age}</p>
</div>`;
四、 箭头函数
不改变 this 的指向,this 指向定义时候的实例
() => {}
五、 默认参数
5.1 默认参数的使用方法
function f(x, y = 7, z = 21) {
return x + y + z;
}
5.2 必填参数检查
es6 还可以对必填参数进行检查
function checkParams() {
throw new Error("params can't be empty");
}
function f(x = checkParams(), y = 2, z = 3) {
return x + y + z;
}
try {
f();
} catch (error) {
console.log(error);
}
5.3 可变参数操作
用一个求和的例子去说明 es6 对于可变参数的操作
// ES5对数据可变参数进行求和
function sum() {
// arguments是伪数组,需要通过array的原型方法对其进行操作
var arr = Array.prototype.slice.call(arguments);
var sum = 0;
arr.forEach(function(item) {
sum += item * 1;
});
return sum;
}
console.log(sum(1, 2, 3, 6));
// ES6对于可变参数进行求和
// ...扩展运算符
function sum1(...arr) {
let sum = 0;
arr.forEach(item => {
sum += item * 1;
});
return sum;
}
console.log(sum1(1, 2, 3, 6));
六、 扩展运算符
有很多用途,这里只是简单的介绍一下
- 数组合并
// es5写法
var params = [1, true, 'test'];
var arr = [2, '合并'].concat(params);
console.log(arr);
// es6的写法
var params = [1, true, 'test'];
var arr = [2, '合并', ...params];
console.log(arr);
七、 for...of
for...of循环会直接拿到值,而不是拿到数组的索引。但是对象不能使用for...of。
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
八、 class
8.1 继承
在 es5 中继承都是绑定原型,实现继承
例子:
function Animal(color) {
this.color = color;
}
Animal.prototype.eat = function() {
console.log(this.color + '色的Animal eat');
};
function Dog(color) {
Animal.call(this, color);
}
var _prototype = Object.create(Animal.prototype);
_prototype.constructor = Dog.prototype.constructor;
Dog.prototype = _prototype;
var hashiqi = new Dog('red');
console.log(hashiqi);
hashiqi.eat();
在 es6 中通过使用 class 定义原型及实现原型的继承
class Animal {
constructor(name) {
this.name = name;
}
eat() {
alert(`${this.name} eat`);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
eat() {
console.log('eat方法重写咯');
}
say() {
alert(`${this.name} say`);
}
}
const dog = new Dog('哈士奇');
dog.say();
dog.eat();
8.2 set,get 方法
在 class 中可以对一个属性定义 set 和 get 方法。
class Car {
constructor() {
this.arr = [];
}
set menu(data) {
this.arr.push(data);
}
get menu() {
return this.arr;
}
}
let bmw = new Car();
bmw.menu = '底盘';
console.log(bmw.menu);
8.3 static 方法
在 class 中可以像 php 的面向对象一样,定义一个静态方法。在访问静态方法时不需要new,可以直接调用。
class Car {
constructor() {
this.arr = [];
}
set menu(data) {
this.arr.push(data);
}
get menu() {
return this.arr;
}
static init() {
console.log('这个是init方法');
}
}
Car.init();
8.4 Class 和普通构造函数有什么区别
- Class 在语法上更加贴合面向对象的写法
- Class 实现继承更加易读,易理解
- Class 更加易于 java 等后端学习
- 本质还是语法糖,还是使用 prototype
九、 Set,Map
9.1 Set
Set 属于一个构造函数,需要使用new关键字去定义。
new 之后生成的 Set 包含了很多方法和属性:
-
在 Set 对象中可以自动去重。
-
Set 对象不是一个数组,可以使用扩展运算符将 Set 对象格式化成数组。
-
可以使用
add()方法向new出来的 Set 对象添加内容。 -
Set 对象可以使用
size属性可以获取长度。 -
使用
has()方法去判断对象中是否包含某一项。 -
使用
delete()方法去删除某一项。 -
使用
clear()方法清空 Set 对象。
例:
let arr = new Set('123');
arr.add('4');
arr.add('4');
console.log(arr); // Set(4) {"1", "2", "3", "4"}
console.log([...arr]); // [1, 2, 3, 4]
console.log(arr.size); // 4
console.log(arr.has('4')); // true
arr.delete('1');
console.log(arr); // Set(3) {"2", "3", "4"}
for (const item of arr) {
console.log(item); // 循环显示出每一项
}
arr.clear();
console.log(arr); // Set(0) {}
9.2 Map
Map 和 Set 其实是类似的,都要使用new实例化一个对象,只不过 Map 中,每一项的类型(key)可以是多种多样的。
例:
let map = new Map();
let fun = function() {};
let obj = {};
map.set(fun, '🍌');
map.set(obj, '🍎');
console.log(map);
使用set给 Map 添加key-value,Map 的 key 可以是函数,也可以是对象。

Map 对象也拥有像 Set 对象一些特有的方法和属性,比如has(),delete(),get(),size,clear()。
let map = new Map();
let fun = function() {};
let obj = {};
map.set(fun, '🍌');
map.set(obj, '🍎');
console.log(map.size); // 2
console.log(map.has(fun)); // true
console.log(map.get(fun)); // 🍌
map.delete(fun);
console.log(map); // Map(1) { {…} => "🍎" }
map.clear();
console.log(map); // Map(0) {}
阅读完后两部曲
- 喜欢的小伙伴点个赞吧,感觉对身边人有帮助的,麻烦动动手指,分享一下。非常感谢各位花时间阅读完,同时很感谢各位的点赞和分享。
- 希望各位关注一下我的公众号吧,新的文章第一时间发到公众号,公众号主要发一些个人随笔、读书笔记、还有一些技术热点和实时热点,并且还有非常吸引人的我个人自费抽奖活动哦~
