Phi*_*sky 6 javascript proxy-classes ecmascript-6
具有以下目的:
let obj = { id: 0 };
Run Code Online (Sandbox Code Playgroud)
和以下内容Proxy:
let objProxy = new Proxy(obj, {
get: (target, name) => {
if (name == "id")
return "id from proxy";
}});
Run Code Online (Sandbox Code Playgroud)
是否可以Proxy在Object.assign()(或对象传播算子,其afaik只是其语法糖Object.assign())之后“保留” ?
let objProxyNew = Object.assign({}, objProxy); // i.e. {...objProxy};
Run Code Online (Sandbox Code Playgroud)
这样objProxyNew.id返回"id from proxy"?
似乎我是第三个遇到完全相同问题的人,这是我在 stackoverflow 上找到的最接近的问题,但它没有真正的答案,所以我不得不自己调查。
偶然地,菲利普在他的例子中想要的行为是默认行为,所以没有必要改变:
let obj = { id: 0 };
let objProxy = new Proxy(obj, {
get: (target, name) => {
if (name == "id")
return "id from proxy";
}});
let objProxyNew = Object.assign({}, objProxy);
console.log(objProxyNew.id); // "id from proxy"Run Code Online (Sandbox Code Playgroud)
但这仅适用于代理对象上的属性名称与最终对象相同的简单代理。
{...obj}javascript 代理对象让我们举一个更复杂的例子,一个“zip”操作的代理(将单独的键和值数组组合成一个对象):
let objProxy = new Proxy({
keys: ["a", "b", "c", "d"],
values: [1, 3, 5, 7]
}, {
get(target, name) {
var index = target.keys.indexOf(name);
return index >= 0 ? target.values[target.keys.indexOf(name)] : false
}
});
console.log(objProxy.c); // 5
console.log({...objProxy}); // {keys: undefined, values: undefined}
Run Code Online (Sandbox Code Playgroud)
现在我们从原始对象中获得了属性,但没有它们的值,因为代理不为“键”和“值”属性返回任何值。
正如我发现的那样,发生这种情况是因为我们没有为“ownKeys”定义陷阱,并且Object.getOwnPropertyNames(target)默认情况下会被调用。
扩展代理:
ownKeys(target) { return target.keys; }
Run Code Online (Sandbox Code Playgroud)
更糟糕的是,现在根本没有克隆任何属性:
console.log({...objProxy}); // {}
Run Code Online (Sandbox Code Playgroud)
现在发生的是 Object.assign 调用Object.getOwnPropertyDescriptor“ownKeys”函数返回的每个键。默认情况下,属性描述符是从“目标”检索的,但我们可以使用另一个名为“getOwnPropertyDescriptor”的陷阱再次更改它:
let objProxy = new Proxy({
keys: ["a", "b", "c", "d"],
values: [1, 3, 5, 7]
}, {
get(target, name) {
var index = target.keys.indexOf(name);
return index >= 0 ? target.values[index] : false
},
ownKeys(target) {
return target.keys;
},
getOwnPropertyDescriptor(target, name) {
return { value: this.get(target, name), configurable: true, enumerable: true };
}
});
Run Code Online (Sandbox Code Playgroud)
enumerable控制哪些属性将被克隆并在控制台中可见。
configurable必须为代理属性设置,否则我们会得到错误:
VM1028:1 未捕获的类型错误:代理上的“getOwnPropertyDescriptor”:陷阱报告了属性“a”的不可配置性,该属性在代理目标中不存在或可配置:1:1
我们还需要将“writable”设置为“true”才能在严格模式下设置属性。
value似乎不被Object.assign其他框架或实现使用但可能被其他框架或实现使用。如果实际获取值的成本很高,我们可以将其定义为 getter:
get value() { return this.get(target, name); }
Run Code Online (Sandbox Code Playgroud)
为了支持in操作符并有一致的实现,我们还应该实现“has”陷阱。所以最终的实现可以是这样的:
let objProxy = new Proxy({
keys: ["a", "b", "c", "d"],
values: [1, 3, 5, 7]
}, {
get(target, name) {
var index = target.keys.indexOf(name);
return index >= 0 ? target.values[target.keys.indexOf(name)] : false
}
});
console.log(objProxy.c); // 5
console.log({...objProxy}); // {keys: undefined, values: undefined}
Run Code Online (Sandbox Code Playgroud)
[...obj]javascript 代理对象另一个故事是支持[...objProxy]- 在这里,[Symbol.iterator]被调用,我们需要在 getter 中定义:
ownKeys(target) { return target.keys; }
Run Code Online (Sandbox Code Playgroud)
我们也可以将“Symbol.iterator”代理到原始对象:
return () => target.values[Symbol.iterator]();
Run Code Online (Sandbox Code Playgroud)
或者
return target.values[Symbol.iterator].bind(target.values);
Run Code Online (Sandbox Code Playgroud)
我们需要重新绑定原始上下文,否则将为 Proxy 对象执行迭代器
| 归档时间: |
|
| 查看次数: |
808 次 |
| 最近记录: |