【发布时间】:2018-09-14 04:45:23
【问题描述】:
例子:
let foo = {bar: 'baz', method() { this.bar = 'baz2' }}
let fooProxy = new Proxy(foo, {set(target, key, val) { console.log('set trap triggered!') }})
fooProxy.bar = 'any value' // as expected: set trap triggered!
foo.method() // trap not triggered
为什么会这样?如何从目标对象内部强制触发陷阱?
编辑,主要是为了向@Bergi解释这个:
我的主要目标是拦截对 foo 对象的任何更改,因此我可以设置属性,例如foo.changed 为 true。另外,我想拦截对具有数组/对象类型的 foo 属性的更改。你知道,如果我设置 foo 的属性,一切都很好,但是当我例如推送到一个数组,然后代理无法拦截它。所以我也需要将数组/对象属性转换为代理(我称它们为 ArrayProxy 和 ObjectProxy)。
这是我的代码(打字稿):
// Category.ts
class Category extends Model {
title: string = ''
products: Product[] = []
}
// Model.ts
abstract class Model extends BaseModel {
constructor() {
return new Proxy(this, {
set (target, key, val) {
if (Array.isArray(val) {
target[key] = new ArrayProxy(val) // I WANT all array properties to be ArrayProxy but the problem (see below) not let me do that
}
}
})
}
}
// BaseModel.ts
abstract class BaseModel {
constructor(attributes) {
this.setAttributes(attributes)
}
setAttributes(attributes) {
Object.keys(attributes).forEach((key) => {
this[key] = attributes[key] // THE PROBLEM
})
}
}
我已经删除了代码,这无关紧要(例如对象属性和 ObjectProxy 的类似情况)。
如果有更优雅的方式来做我所做的事情,我将非常感激。
【问题讨论】:
-
你当然需要使用
fooProxy.method()。你也不会指望fooProxy.method.call(something)(设置something.bar)来触发代理? -
好吧,普通对象的构造函数对代理一无所知(也不应该知道)。您尝试使用代理解决的actual problem 是什么,您的真实代码是什么?
-
@Phil:你不应该编辑其他人的代码。我不知道该编辑是如何获得批准的。添加分号和使用
const会将您的个人风格强加给其他人。 -
@NurbolAlpysbayev 好吧,您只能在将代理包裹在对象周围之后才能拦截对对象的更改,这将在对象构造之后发生。不,拦截对嵌套数组/对象的更改是一个完全不同的主题(参见例如here 和许多其他帖子),请不要偏离这个讨论。
-
@NurbolAlpysbayev 您应该简单地在
Model和BaseModel之间交换代理。你可能注意到Category,它在扩展Model(构造函数返回一个代理)的东西上工作得很好。
标签: javascript ecmascript-6 es6-proxy