ES6
image.png

proxy

Proxy 也就是代理,可以帮助我们完成很多事情,例如对数据的处理,对构造函数的处理,对数据的验证,说白了,就是在我们访问对象前添加了一层拦截,可以过滤很多操作,而这些过滤,由你来定义。

  1. let p = new Proxy(target, handler);

参数

  1. target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  2. handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。具体的handler相关函数请查阅官网
  1. let xiaohong = {
  2. name: 'xiaohong',
  3. age: 34
  4. }
  5. let xh = new Proxy(xiaohong, {
  6. // target 为对象
  7. // key 为对象的键值
  8. get(target, key){
  9. console.log(`${target[key]} is ${key}`)
  10. return target[key]; // get 的时候需要有返回值
  11. },
  12. // target 为对象
  13. // key 为对象的键值
  14. // value 为需要设置的值
  15. set(target, key, value) {
  16. // console.log(`${target[key]} is ${key} + ${value}`)
  17. target[key] = value;
  18. // return Reflect.set(target, key, value);
  19. return true; // set 只有在返回值为true时,才表示设置成功
  20. }
  21. })
  22. xh.name = 'xiaohong123'
  23. console.log(xh.age)
  24. console.log(xh.name)

reflect

Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect对象的设计目的有这样几个。
(1) 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
(2) 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
(3) 让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。

Reflect对象一共有 13 个静态方法。

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

上面这些方法的作用,大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。

promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。

  1. const promise = new Promise(function(resolve, reject) {
  2. // ... some code
  3. if (/* 异步操作成功 */){
  4. resolve(value);
  5. } else {
  6. reject(error);
  7. }
  8. });

set / map

Set 是ES6提供的新的数据结构,它类似于数组,但是成员都是唯一的,没有重复值。Set中的成员可以是数组,数字,字符串,甚至是对象,不需要像数组一样,必须所有的字段类型相同。
WeakSet的结构与Set类似,也不是重复值的集合,和Set的区别主要有三点:

  1. WeakSet 中的成员只能是对象,不能是其他类型
  2. WeakSet中的对象都是弱引用,垃圾回收机制不考虑WeakSet对该对象的引用,当不使用时,垃圾回收机制会直接回收该对象
  3. WeakSet不可遍历

Set实例的属性:

  • Set.propotype.constructor
  • Set.propotype.size

Set实例的方法:

  • Set.propotype.add(value);
  • Set.propotype.delete(value);
  • Set.propotype.has(value);
  • Set.propotye.clear();

Set实例遍历的方法:

  • Set.prototype.keys();
  • Set.prototype.values();
  • Set.prototype.entries();
  • Set.prototype.forEach();

WeakSet的方法:

  • WeakSet.prototype.add(value);
  • WeakSet.prototype.delete(value);
  • WeakSet.prototype.has(value);

JavaScript对象本质上是键值对的集合(Object), 本质上是键值对的集合。但是传统上只能用字符串当键,这对它的使用带来很大的限制。因此,ES6提供了Map结构,类似于数组,也是键值对的集合,但是键不限于字符串,各种类型的值都可以当作键。

  1. let map = new Map();
  2. map.set('name', 'beebo');

Map实例的属性:

  • map.size
  • Map.prototype.set(key, vaule);
  • Map.prototype.get(key);
  • Map.prototype.has(key);
  • Map.prototype.delete(key);
  • Map.prototype.clear();

Map实例的遍历方法:

  • Map.prototype.keys();
  • Map.prototype.values();
  • Map.prototype.entries();
  • Map.prototype.forEach();

    Map与其他数据结构的转换

  1. Map转数组 — 扩展运算符 […map]
  2. 数组转Map — 将数组传入Map的构造函数中
  3. Map转对象
  4. 对象转Map
  5. Map转JSON
  6. JSON转Map