记录一些迁移到 ES6 、ES7 的笔记,主要参考了 ECMAScript 6 入门

新增了很多内容,这里只记录常用的。

变量声明

ES6 新增了两个变量声明的关键词 letconst

let 用于代替 var

let 不会像 var 那样声明为全局变量

1
2
3
4
5
6
7
{
let a = 10;
var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

所以也不需要 IIFE 了。因为 let 声明相当于块级作用域

1
2
3
4
5
6
7
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}

const 用于声明只读的常量

1
2
3
4
5
const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

详情

解构

ES6 增加了变量解构赋值

1
2
3
4
5
var a = 1;
var b = 2;
var c = 3;
// ES6
let [a, b, c] = [1, 2, 3];

解构赋值很灵活

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 // []

解构赋值可用于多值返回,参数解构等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 返回一个数组

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});

字符串

字符串操作新增了很多方法,主要说几个常用的。

includes() 判断是否包含特定字符串

startsWith() 判断是否以特定字符串开头

endsWith() 判断是否以特定字符串结尾

1
2
3
4
5
6
7
8
9
var s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

ES6 还新增了模板字符串,用\` 包裹 。模板字符串中的空格和换行都会保留。

1
2
console.log(`string text line 1
string text line 2`);

还可以用作插值表达式

1
2
3
// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

数值

ES6 新增二进制和八进制的表示法

1
2
0b10000000000 === 1024 //true
0o2000 === 1024 //true

还新增了一些处理数字的方法,常用的有

Number.isNan() 判断是否为 NaN

1
2
3
4
5
6
7
8
9
NaN === NaN // false
Number.isNaN(NaN) // true

Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true'/0) // true
Number.isNaN('true'/'true') // true

Math.truct() 截断小数

1
2
3
4
5
6
7
8
9
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
Math.trunc('123.456') // 123
Math.trunc(NaN); // NaN
Math.trunc('foo'); // NaN
Math.trunc(); // NaN

Math.sign() 判断正负

1
2
3
4
5
6
7
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(NaN) // NaN
Math.sign('foo'); // NaN
Math.sign(); // NaN

此外还新增了指数运算符 **

1
2
3
4
5
6
2 ** 2 // 4
2 ** 3 // 8

let a = 2;
a **= 2;
// 等同于 a = a ** 2 = a * a;

数组

数组也新增了方法,常用的有

Array.from() 用于将类数组转为数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});

// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}

Array.of() 将一组值转化为数组

1
2
3
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

find() 返回符合条件的元素

1
2
[1, 4, -5, 10].find((n) => n < 0)
// -5

findIndex() 返回符合条件的元素索引

1
2
3
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2

所以以后使用 indexOf 时优先考虑使用 includes()find()findIndex()

函数声明

ES6 新增了胖箭头函数用于声明 $\lambda$ 表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var f = v => v;
// 等同于
var f = function(v) {
return v;
};

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};

使用箭头函数还有一个好处就是不用手动绑定 this

ES6 新增了对参数默认值的支持

1
2
3
4
5
6
7
function log(x, y = 'World') {
console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

可以和解构赋值搭配使用

1
2
3
4
5
6
7
8
function foo({x, y = 5}) {
console.log(x, y);
}

foo({}) // undefined, 5
foo({x: 1}) // 1, 5
foo({x: 1, y: 2}) // 1, 2
foo() // TypeError: Cannot read property 'x' of undefined

还新增了不定参数的支持

1
2
3
4
5
6
7
8
9
10
11
function add(...values) {
let sum = 0;

for (var val of values) {
sum += val;
}

return sum;
}

add(2, 5, 3) // 10

新增扩展运算符,将数组化为元素序列

1
2
3
4
5
6
7
8
console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

可以用于合并数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];

// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

还可以搭配解构赋值使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ES5
let a = list[0], rest = list.slice(1)
// ES6
let [a, ...rest] = list

const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest // []:

const [first, ...rest] = ["foo"];
first // "foo"
rest // []

对象

ES6 新增对象声明语法糖 class

用传统的原型链声明一个对象

1
2
3
4
5
6
7
8
9
10
function Point(x, y) {
this.x = x;
this.y = y;
}

Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

class 语法糖

1
2
3
4
5
6
7
8
9
10
11
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}

toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}

还可以使用 extends 来继承,使用 super() 调用父类函数

1
2
3
4
5
6
7
class A {}

class B extends A {
constructor() {
super();
}
}

新增了一些简化表示法

属性简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var foo = 'bar';
var baz = {foo};
baz // {foo: "bar"}

// 等同于
var baz = {foo: foo};

function f(x, y) {
return {x, y};
}

// 等同于
function f(x, y) {
return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

方法简写

1
2
3
4
5
6
7
8
9
10
11
12
var o = {
method() {
return "Hello!";
}
};

// 等同于
var o = {
method: function() {
return "Hello!";
}
};

详情

Promise

ES6 Promise

迭代

新增了 for ... of 迭代,相当于其他语言的 for each

1
2
3
4
5
6
7
8
9
var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
console.log(a); // 0 1 2 3
}

for (let a of arr) {
console.log(a); // a b c d
}

还可搭配新增的 entries()key()value() 使用

1
2
3
4
5
6
7
let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

代码风格

两空格缩进,不添加分号。