proxy、reflect
Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
var proxy = new Proxy(target, handler);
其中target, handler其实都是对象,target为目标、要代理的对象,handler定义了一堆代理的方法。
proxy内置13个方法,与Reflect方法对应。
方法 | proxy | reflect |
---|---|---|
get(); | 拦截读取操作 | (target,name,receiver)查找并返回target的name属性 |
set(); | 拦截赋值操作 | (target,name,value, receiver) |
apply(); | 拦截函数的调用、call 和 apply 操作 | Reflect.apply(Math.min, Math, age) === Math.min.apply(Math, age) |
has(); | 可以拦截hasProperty的操作,返回一个布尔值。对in方法生效,对for in不生效。 | (obj,name) Reflect.has(obj,name) => true |
construct(); | // 拦截new命令,必须返回对象,否则报错。 | new Greet(‘落白’) === Reflect.construct(Greet, [‘落白’]) |
deleteProperty(); | 拦截delete操作。 configrable的属性不能被此方法输出,否则报错。 | (obj, ‘name’)删除成功或属性不存在则返回true |
defineProperty(); | 拦截defineProperty方法。 | Object.defineProperty() === Reflect.defineProperty() |
getOwnPropertyDescriptor(); | 拦截Object.getOwnPropertyDescriptor(); | === |
getPrototypeOf(); | 拦截对象原型。 | let myobj = new Fancy(); Object.getPrototypeOf(myobj) === Reflect.getPrototypeOf(myObj) === Fancy.prototype(); |
isExtensible(); | 拦截Object.isExtensible(); | 返回布尔值,表对象是否可拓展 |
ownKeys(); | 拦截对象自身属性的读取(Object.keys().. | 返回对线的所有属性 |
preventExtensions(); | 拦截Object.preventExtensions() | 使对象不可扩展 |
setPrototypeOf(); | 拦截Object.setPrototypeOf(); | (obj,newProto) |
proxy.revocable用于取消Proxy实例。
目标对象的this会指向Proxy代理。
definePropety
语法
Object.defineProperty(obj, prop, descriptor)
obj: 要在其上定义属性的对象。
prop: 要定义或修改的属性的名称。
descriptor: 将被定义或修改的属性的描述符。
- configurable 可配置、删除
- enumerable 可枚举
数据描述符: - value 该属性对应的值
- writable 可读写
存取描述符: - get: 提供 getter 的方法,默认为 undefined
- set: 提供 setter 的方法, 默认为 undefined
** 属性描述符必须是数据描述符或者存取描述符两种形式之一,不能同时是两者。
实现简单的双向绑定
数据驱动dom,即当数据改变的时候,自动进行渲染工作。举个例子:
HTML 中有个 span 标签和 button 标签
1 2 | <span id="container">1</span> <button id="button">点击加 1</button> |
当点击按钮的时候,span 标签里的值加 1。
1 2 3 4 | document.querySelector('#button').addEventListener("click", function(){ var container = document.querySelector("#container"); container.innerHTML = Number(container.innerHTML) + 1; }); |
defineProperty方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var obj = { value: 1 } // 储存 obj.value 的值 var value = 1; Object.defineProperty(obj, "value", { get: function() { return value; }, set: function(newValue) { value = newValue; document.getElementById('container').innerHTML = newValue; } }); document.getElementById('button').addEventListener("click", function() { obj.value += 1; }); |
proxy实现
var obj = {
value: 1
}
// 储存 obj.value 的值
var value = 1;
var proxy = new Proxy(obj, {
get: (target, key) => value,
set: (target, key, newValue) => {
value = newValue;
document.getElementById('container').innerHTML = newValue;
}
})
document.getElementById('button').addEventListener("click", function () {
proxy.value += 1;
});
参考资料:
《ES6标准入门》
ES6 系列之 defineProperty 与 proxy