1. 1. 模块 module
  2. 2.
  3. 3. 模块 module
  4. 4. 循环与迭代器 Iterator
  5. 5. 生成器 Generator
  6. 6. 集合类型
    1. 6.1. Set & Map
    2. 6.2. WeakSet & WeakMap
  7. 7. 数组或对象循环遍历的方法对比
    1. 7.1. for/while 循环语句
    2. 7.2. forEach 方法
    3. 7.3. for…in 语句
    4. 7.4. for…of 语句
    5. 7.5. map() & filter() & reduce()
ES6 核心向新特性(02)

模块 module

1
2
import { sayHi } from './people';
export default sayHi;

注意点:使用default导出时要尽量将其他模板需要使用的部分属性导出,不要导出整个对象,因为这样会导出一些不需要的东西,如果使用模块按需内容导出,部分ECMAScript6的打包工具可以使用静态树分析的方法来自动移除程序运行时不需要的代码。

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
// 类声明
class Aminal {
// 类中只能包含一个名为constructor的特殊方法
constructor() {
// ...
}
}
// extends 创建子类
class People extends Aminal {
constructor(contents = {}) {
super(); // 调用父类的构造函数
this.name = contents.name;
this.family = contents.family;
}
sayHi() {
console.log(`Hello {this.name} {this.family}`);
}
}

let boy = new People({
name: 'ouven',
family: 'zhang'
});

boy.sayHi(); // Hello ouven zhang

模块 module

1
2
import { sayHi } from './people';
export default sayHi;

注意点:使用default导出时要尽量将其他模板需要使用的部分属性导出,不要导出整个对象,因为这样会导出一些不需要的东西,如果使用模块按需内容导出,部分ECMAScript6的打包工具可以使用静态树分析的方法来自动移除程序运行时不需要的代码。

循环与迭代器 Iterator

在 es6 阶段,除了do...whilefor循环,还可以使用for...in来遍历对象。Iterator迭代器的加入让遍历数组、对象和集合的方式更加灵活可控,Iterator可以控制每次单步循环触发的时机,不用一次遍历所有的循环。

for...of遍历实现

1
2
3
4
5
const numbers = [1, 2, 3, 4, 5];

for(let number of numbers) {
console.log(number);
}

迭代器遍历数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const numbers = [1, 2, 3, 4, 5];

let iterator = numbers[Symbol.iterator]();
let result = iterator.next();
console.log(result.value); // 1

result = iterator.next();
console.log(result.value); // 2

result = iterator.next();
console.log(result.value); // 3

result = iterator.next();
console.log(result.value); // 4

result = iterator.next();
console.log(result.value); // 5

对比
Iterator 可以在循环开始后任意的地方进行数组的单步循环,当循环迭代中每次单步循环操作都不一样时,使用 Iterator 更加的方便。如果使用for...of则需要不断判断执行的次数来执行不同的单步循环。
注意点
每次 Iterator 调用next()都会返回一个对象{done: false, value: item}done的属性是布尔值,表示循环遍历是否完成,value则是每一步next()调用获取到的值。

生成器 Generator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const generator = function* () {
const numbers = [1, 2, 3, 4, 5];
for(let number of numbers) {
yield console.log(number);
}
}

let result = generator();

result.next(); // 1
// ...doSomething
result.next(); // 2
// ...doSomething
result.next(); // 3
// ...doSomething
result.next(); // 4
// ...doSomething
result.next(); // 5
// ...doSomething

Generator 是针对函数内代码块的执行控制,如果将一个特殊函数的代码使用yield关键字来分割成多个不同的代码段,那么每次 Generator 调用next()都只会执行yield关键字之间的一段代码。Generator 可以认为是一个可中断执行的特殊函数,声明方法是在函数名后面加上*来与普通函数区分。
注意点
Generator 遇到yield关键字会暂停往后执行,但并不表示后面的程序就不执行了。如果console.log(number)是一个耗时的工作,那么程序只在 Generator 里面暂停,外面的程序仍会继续执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const generator = function* () {
const numbers = [1, 2, 3, 4, 5];
for(let number of numbers) {
yield setTimeout(function() {
console.log(number);
}, 3000);
}
}

let result = generator();
let done = result.next();
while(!done.done) {
done = result.next();
}
console.log('finish');
// 输出
finish
1
2
3
4
5

集合类型

Set & Map

为什么有了数组和对象来进行存储数据还要要使用 Map & Set

  • 对象的键名一般只能是字符串,而不能是一个对象;
  • 对象没有直接获取属性个数等这些方便操作的方法;
  • 对于对象的任何操作都需要进入对象的内部数据中完成,如查找、删除某个值必须循环遍历对象内部的所有键值对来完成。

Set的基本用法

1
2
3
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]

Set 不会添加重复的值,并且可以接受一个数组(或者具有 Iterable 接口的其他数据解构)作为参数,用来初始化。
Map的基本用法

1
2
3
4
5
6
7
8
9
const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

Map 类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以作为键。

WeakSet & WeakMap

WeakSet 和 WeakMap 则对应着 Set 和 Map 的优化类型,所以某种程度上,为了让程序开发更加方便,我妈有必要引入集合这类更为高效的类型。WeakSet 和 WeakMap 在生成时有更加严格的限制:WeakSet 只存储对象类型的元素,不能遍历,没有size属性;WeakMap 只接受基本类型的值作为键名,没有keysvaluesentries等遍历方法,也没有size属性。
WeakSet的基本用法

1
2
3
4
5
6
7
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}

const b = [3, 4];
const ws = new WeakSet(b);
// Uncaught TypeError: Invalid value used in weak set(…)

WeakMap的基本用法

1
2
3
4
5
6
7
8
const wm1 = new WeakMap();
const key = {foo: 1};
wm1.set(key, 2);
wm1.get(key) // 2

const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!

数组或对象循环遍历的方法对比

for/while 循环语句

1
2
3
4
let arr = [1, 2, 3];
for(let = 0, len = arr.length; i < len; i++) {
console.log(arr[i]);
}

所有语言都会涉及的循环。不过单纯的for/while能力有限,而且性能上也堪忧。而且必须借助特定的结构才能遍历数据结构。

forEach 方法

1
2
3
[1, 2, 3].forEach(function(value, index) {
console.log(index + ':' + value);
});

优点:可以同时获取index和value,不必再像以前遍历数组那样,还要再在for去获取值。
缺点:仅支持数组。而且一旦调用,会完全遍历一次,break, continue, return都无效。
应用场景:仅在遍历数组的时候使用。

for…in 语句

1
2
3
4
let obj = {a: 1, b: 2,c: 3};
for(let key in obj) {
console.log(obj[key]);
}

优点:它可以支持所有对象类型的数据,包括数组,甚至是函数等,而且语法简单。且不同于forEach方法,它可以与break、continue和return配合使用。
缺点:循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。主要是为遍历对象而设计的,不适用于遍历数组。
应用场景: 遍历常用对象(如例子)

for…of 语句

1
2
3
4
5
6
7
var list = new Map();
list.set('a', 1);
list.set('b', 2);
list.set('c', 3);
for(var [key, value] of list) {
console.log(key + ':' + value);
}

for...of是ES6新增的语法,它是基于ES6新增的Iterator和Symbol开发的。
优点:在遍历中直接取值。感觉上和for...in形成互补,一个在遍历中取键名,另一个取值。另一个优点是,它可以遍历任何部署了 Iterator 接口的数据结构(如 Set 和 Map),甚至是非 JavaScript 的数据类型,即自己定义的数据结构。
缺点:对于普通的对象,for...of结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。
应用场景:推荐应用于Map上的遍历。

map() & filter() & reduce()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var arr = [1, 2, 3];

arr.map(function(element) {
return element + 1;
});
// [2, 3, 4]

arr.filter(function(element) {
return element > 1;
})
// [2, 3]

var result = arr.reduce(function(prev, element) {
return prev + element;
}, 0);
// 5

应用场景:这三个方法都是是 Array 中的方法,常用于数组中的数值的处理。map主要用于对存储的数据进行加工,filter偏向于过滤数据,reduce用于计算总和。

学习参考:
ECMAScript 6入门——阮一峰
《现代前端技术解析》