diff --git a/docs/proxy.md b/docs/proxy.md index 96d8a2d..6095d2a 100644 --- a/docs/proxy.md +++ b/docs/proxy.md @@ -769,19 +769,44 @@ revoke(); proxy.foo // TypeError: Revoked ``` -Proxy.revocable方法返回一个对象,该对象的proxy属性是Proxy实例,revoke属性是一个函数,可以取消Proxy实例。上面代码中,当执行revoke函数之后,再访问Proxy实例,就会抛出一个错误。 +`Proxy.revocable`方法返回一个对象,该对象的`proxy`属性是`Proxy`实例,`revoke`属性是一个函数,可以取消`Proxy`实例。上面代码中,当执行`revoke`函数之后,再访问`Proxy`实例,就会抛出一个错误。 ## Reflect概述 -Reflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新API。Reflect对象的设计目的有这样几个。 +`Reflect`对象与`Proxy`对象一样,也是ES6为了操作对象而提供的新API。`Reflect`对象的设计目的有这样几个。 -(1) 将Object对象的一些明显属于语言层面的方法,放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。 +(1) 将`Object`对象的一些明显属于语言内部的方法(比如`Object.defineProperty`),放到`Reflect`对象上。现阶段,某些方法同时在`Object`和`Reflect`对象上部署,未来的新方法将只部署在`Reflect`对象上。 -(2) 修改某些Object方法的返回结果,让其变得更合理。比如,`Object.defineProperty(obj, name, desc)`在无法定义属性时,会抛出一个错误,而`Reflect.defineProperty(obj, name, desc)`则会返回false。 +(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)`让它们变成了函数行为。 +```javascript +// 老写法 +try { + Object.defineProperty(target, property, attributes); + // success +} catch (e) { + // failure +} -(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。 +// 新写法 +if (Reflect.defineProperty(target, property, attributes)) { + // success +} else { + // failure +} +``` + +(3) 让`Object`操作都变成函数行为。某些`Object`操作是命令式,比如`name in obj`和`delete obj[name]`,而`Reflect.has(obj, name)`和`Reflect.deleteProperty(obj, name)`让它们变成了函数行为。 + +```javascript +// 老写法 +'assign' in Object // true + +// 新写法 +Reflect.has(Object, 'assign') // true +``` + +(4)`Reflect`对象的方法与`Proxy`对象的方法一一对应,只要是`Proxy`对象的方法,就能在`Reflect`对象上找到对应的方法。这就让`Proxy`对象可以方便地调用对应的`Reflect`方法,完成默认行为,作为修改行为的基础。也就是说,不管`Proxy`怎么修改默认行为,你总可以在`Reflect`上获取默认行为。 ```javascript Proxy(target, { @@ -795,7 +820,7 @@ Proxy(target, { }); ``` -上面代码中,Proxy方法拦截target对象的属性赋值行为。它采用`Reflect.set`方法将值赋值给对象的属性,然后再部署额外的功能。 +上面代码中,`Proxy`方法拦截`target`对象的属性赋值行为。它采用`Reflect.set`方法将值赋值给对象的属性,然后再部署额外的功能。 下面是另一个例子。 @@ -816,11 +841,21 @@ var loggedObj = new Proxy(obj, { }); ``` -上面代码中,每一个Proxy对象的拦截操作(`get`、`delete`、`has`),内部都调用对应的Reflect方法,保证原生行为能够正常执行。添加的工作,就是将每一个操作输出一行日志。 +上面代码中,每一个`Proxy`对象的拦截操作(`get`、`delete`、`has`),内部都调用对应的Reflect方法,保证原生行为能够正常执行。添加的工作,就是将每一个操作输出一行日志。 + +有了`Reflect`对象以后,很多操作会更易读。 + +```javascript +// 老写法 +Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1 + +// 新写法 +Reflect.apply(Math.floor, undefined, [1.75]) // 1 +``` ## Reflect对象的方法 -Reflect对象的方法清单如下,共14个。 +`Reflect`对象的方法清单如下,共14个。 - Reflect.apply(target,thisArg,args) - Reflect.construct(target,args) @@ -839,11 +874,11 @@ Reflect对象的方法清单如下,共14个。 上面这些方法的作用,大部分与`Object`对象的同名方法的作用都是相同的,而且它与`Proxy`对象的方法是一一对应的。下面是对其中几个方法的解释。 -**(1)Reflect.get(target,name,receiver)** +**(1)Reflect.get(target, name, receiver)** -查找并返回target对象的name属性,如果没有该属性,则返回undefined。 +查找并返回`target`对象的`name`属性,如果没有该属性,则返回`undefined`。 -如果name属性部署了读取函数,则读取函数的this绑定receiver。 +如果`name`属性部署了读取函数,则读取函数的this绑定`receiver`。 ```javascript var obj = { @@ -858,7 +893,7 @@ Reflect.get(obj, "foo", wrapper); **(2)Reflect.set(target, name, value, receiver)** -设置target对象的name属性等于value。如果name属性设置了赋值函数,则赋值函数的this绑定receiver。 +设置`target`对象的`name`属性等于`value`。如果`name`属性设置了赋值函数,则赋值函数的`this`绑定`receiver`。 **(3)Reflect.has(obj, name)**