我想对Proxy object进行试验,并得到了一些意想不到的结果,如下所示:
function Person(first, last, age) {
this.first = first;
this.last = last;
this.age = age;
}
Person.prototype.greeting = function () {
return `Hello my name is ${this.first} and I am ${this.age} years old`;
};
因此,在跟踪prototype
对象的修改方式时,我添加了以下包装器:
let validator = {
set: function(target, key, value) {
console.log(`The property ${key} has been updated with ${value}`);
target[key] = value;
return true;
}
};
Person.prototype = new Proxy(Person.prototype, validator);
let george = new Person('George', 'Clooney', 55);
Person.prototype.farewell = function () {
return `Hello my name is ${this.first} and I will see you later`;
};
The property: "farewell" has been updated with: "function () {
return `Hello my name is ${this.first} and I will see you later`;
}"
没别的。
当然,每次我从prototype
添加或删除某些内容时,即Person.prototype
或instance.constructor.prototype
,我都希望看到console.log()
消息。
但是我没有希望在实例上进行设置时看到任何东西,例如:
george.someProp = 'another value'; // did NOT expect to see the console.log()
The property: "first" has been updated with: "george"
The property: "last" has been updated with: "clooney"
The property: "age" has been updated with: "55"
The property: "farewell" has been updated with: "function () {
return `Hello my name is ${this.first} and I will see you later`;
}"
Person.prototype
Proxy {greeting: ƒ, first: "George", last: "Clooney", age: 55, farewell: ƒ, constructor: ƒ}
它在prototype
上设置了所有属性,而在实例上没有设置任何属性,并且每次我在instance
上进行设置时,它都会直接在prototype
上设置。
显然,这不是默认行为,就好像我删除了Proxy
一样,每个用this
设置的属性都将设置在实例本身上,而prototype
将开始为空(或仅使用greeting
函数)。
我在这里想念什么?朝正确方向的观点将不胜感激。
答案 0 :(得分:5)
缺少的事实是,当原型链中有一个Proxy对象时,修改子对象时将调用set处理程序。
在您的示例中,当您在新实例上设置属性时,将执行set陷阱,target
将是包装的Person.prototype
对象,但是有第四个参数, receiver
。此参数指向已访问该属性的对象。
要正确执行属性分配,可以使用Reflect.set
API进行设置:
Reflect.set(target, key, value, receiver);
这就是Reflect
API与代理陷阱参数匹配的原因。
因此,在您的示例中,我们可以使用Reflect API,您将看到Person.prototype
不会被“污染”。
function Person(first, last, age) {
this.first = first;
this.last = last;
this.age = age;
}
Person.prototype.greeting = function () {
return `Hello my name is ${this.first} and I am ${this.age} years old`;
};
const validator = {
set: function(target, key, value, receiver) {
console.log(`The property ${key} has been updated with ${value}`);
Reflect.set(target, key, value, receiver)
return true;
}
};
Person.prototype = new Proxy(Person.prototype, validator);
const george = new Person('George', 'Clooney', 55);
Person.prototype.farewell = function () {
return `Hello my name is ${this.first} and I will see you later`;
};
console.log(george.hasOwnProperty('first')); // true
console.log(Person.prototype.hasOwnProperty('first')); // false