ES6 之 阅读理解

17. Iterator

https://jiafei2333.github.io/2019/09/16/Generator/

是一种接口,为各种不同的数据结构(Array、Object、Map、Set 等)提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of消费。

一刷:
http://es6.ruanyifeng.com/#docs/iterator

18. Generator

https://jiafei2333.github.io/2019/09/16/Generator/

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。

1、一个对象如果要具备可被for…of循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。

1/2刷:
http://es6.ruanyifeng.com/#docs/generator

19. Generator 函数的异步应用

http://es6.ruanyifeng.com/#docs/generator-async

一刷,没怎么看明白,可以二刷继续研究,评论也看看。

20.async 函数

http://es6.ruanyifeng.com/#docs/async

async 函数就是 Generator 函数的语法糖。

1、Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。
2、任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
3、Promise 的回调函数( .then )都存放在一个单独的栈里面,而 await 是暂停执行,所以不完全一样。

一刷

12. Symbol

https://jiafei2333.github.io/2019/09/04/Reflect-Symbol/

Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。

1、Singleton 模式指的是调用一个类,任何时候返回的都是同一个实例。

http://es6.ruanyifeng.com/#docs/symbol
一刷:内置的 Symbol 值 这块内容太琐碎了,没怎么记得。

14. Proxy

https://jiafei2333.github.io/2019/09/04/Object.defineProperty-Proxy/

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

1、ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
2、注意,要使得Proxy起作用,必须针对Proxy实例(上例是proxy对象)进行操作,而不是针对目标对象(上例是空对象)进行操作。
3、虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。
4、《this 问题》 这个可以看看,其他的很多都是Proxy的属性
5、Proxy web服务的客户端。

一刷:
http://es6.ruanyifeng.com/#docs/proxy

15. Reflect

Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。

一刷:
http://es6.ruanyifeng.com/#docs/reflect

10. 11. 对象

10.1. 对象的拓展

1.1 属性的遍历

  • (1)for…in
  • (2)Object.keys(obj)
  • (3)Object.getOwnPropertyNames(obj)
  • (4)Object.getOwnPropertySymbols(obj)
  • (5)Reflect.ownKeys(obj)
    Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

10.1.2 super

我们知道,this关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super,指向当前对象的原型对象。

JavaScript 引擎内部,super.foo等同于Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)。 ??
Object.getPrototypeOf() 返回指定对象的原型。

11.2. 对象的新增方法

11.2.1 Object.is()

比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

1
2
3
4
5
6
7
Object.is({}, {}); // false

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

11.2.2 Object.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

1
Object.assign(target, source1, source2);
  • Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。属性名为 Symbol 值的属性,也会被Object.assign拷贝。

11.2.3 proto属性,Object.setPrototypeOf(),Object.getPrototypeOf()

https://jiafei2333.github.io/2019/09/09/Prototype-Extends/

11.2.4 Object.keys(),Object.values(),Object.entries() 搭配 for…of 使用

也都可以搭配数组 for (let index of ['a', 'b'].keys())

一刷:
http://es6.ruanyifeng.com/#docs/object
http://es6.ruanyifeng.com/#docs/object-methods

9. 数组

9.1. 拓展运算符的应用

http://es6.ruanyifeng.com/#docs/array#%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6%E7%9A%84%E5%BA%94%E7%94%A8

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。
Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。

9.2. Array.from()

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

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

一刷:
http://es6.ruanyifeng.com/#docs/array

8. 函数的拓展

8.1. 函数的 length 属性

函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真,这个个数不算。

8.2. 作用域

** http://es6.ruanyifeng.com/#docs/function#%E4%BD%9C%E7%94%A8%E5%9F%9F

8.3. 箭头函数

  • (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。

1
2
3
4
5
6
7
8
9
10
11
12
var handler = {
id: '123456',

init: function() {
document.addEventListener('click',
event => this.doSomething(event.type), false);
},

doSomething: function(type) {
console.log('Handling ' + type + ' for ' + this.id);
}
};

上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

8.4. 尾调用优化

我们知道,函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

一刷:
http://es6.ruanyifeng.com/#docs/function

13. Set和Map数据结构

Set

https://es6.ruanyifeng.com/#docs/set-map

Set本身是一个构造函数,用来生成Set数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。

【去重】

1
2
3
4
5
let s = new Set([1,2,3,4,5,4,3,2,1]);
console.log([...s]);

let s = new Set([1,2,3,4,5,4,3,2,1]);
console.log(Array.from(s));

【遍历】
keys()、values()、entries() 搭配 for…of

Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。
Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。
数组的map和filter方法也可以间接用于 Set 了。

WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。 ES6 规定 WeakSet 不可遍历。

  • WeakSet 的成员只能是对象,而不能是其他类型的值。
  • WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

Map

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

创建的由来不错:
https://es6.ruanyifeng.com/#docs/set-map#%E5%90%AB%E4%B9%89%E5%92%8C%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95