源自ECMAScript 6入门

简介

ES6的第一个版本,在2015年6月发布,正式名称是《ECMAScript 2015标准》(简称ES2015)。ES6既是一个历史名词,也是一个泛指,含义是5.1版以后的JavaScript的下一代标准,涵盖了ES2015、ES2016、ES2017等等,而ES2015则是正式名称,特指该年发布的正式版本的语言标准。
ES2015~ES6.0
ES2016~ES6.1

let命令

let

  • 声明的变量只在它所在的代码块有效
  • 不存在变量提升
  • 不允许重复声明。

暂时性死区(temporal dead zone,简称TDZ)

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

1
2
3
4
5
6
var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

有些“死区”比较隐蔽,不太容易发现。

1
2
3
4
5
function bar(x = y, y = 2) {
  return [x, y];
}

bar(); // 报错

上面代码中,调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于”死区“。如果y的默认值是x,就不会报错,因为此时x已经声明了。

1
2
3
4
function bar(x = 2, y = x) {
  return [x, y];
}
bar(); // [2, 2]

const命令

const

  • 声明一个只读的常量
  • 一旦声明,就必须立即初始化,且不能改变
  • 只在声明所在的块级作用域内有效
  • 不存在变量提升
  • 存在暂时性死区
  • 不可重复声明
  • 对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址

正则

RegExp构造函数

如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符。

1
2
new RegExp(/abc/ig, 'i').flags
// "i"

u修饰符

ES6对正则表达式添加了u修饰符,含义为“Unicode模式”,用来正确处理大于\uFFFF的Unicode字符

y修饰符

ES6对正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。 y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

1
2
3
4
5
6
7
8
9
var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null

可以说,y修饰符号隐含了头部匹配的标志^

数组

Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构SetMap)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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);
});
// 也可以使用扩展运算符
[...ps];

// arguments对象
function foo() {
  var args = Array.from(arguments);
  // 也可以使用扩展运算符
  var args2 = [...arguments];
}

// 字符串转数组
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']

// set转数组
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']

任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换。

1
2
Array.from({ length: 3 });
// [ undefined, undefined, undefined ]

上面代码中,Array.from返回了一个具有三个成员的数组,每个位置的值都是undefined。扩展运算符转换不了这个对象。

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。

1
2
3
4
5
6
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

Array.of()

Array.of方法用于将一组值,转换为数组。这个方法主要是为了弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。

find()和findIndex()

数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined

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

// find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

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

entries(),keys()和values()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 对键名的遍历
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

// 对键值的遍历
for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

// 对键值对的遍历
for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

// 手动调用遍历器对象的next方法进行遍历。
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
console.log(entries.next().value); // undefined