以下代码演示了"标准" JavaScript中的属性查找规则。它创建一个空对象a
,其原型包含一个属性i
。阅读a.i
给出了原型的值,但是写a.i
会在对象本身中创建一个新属性:
function A() {}
A.prototype = { i: 1 }
a = new A();
console.log(a.i, a.hasOwnProperty('i')); // 1 false
a.i = 2
console.log(a.i, a.hasOwnProperty('i')); // 2 true
但是,如果我们在原型中有一个setter,那么行为就不同了。编写a.i
现在调用setter而不是直接写入对象:
function A() {}
A.prototype = { set i(value) { this._i = value }, _i: 1 }
a = new A();
console.log(a.i, a.hasOwnProperty('i')); // undefined false
console.log(a._i, a.hasOwnProperty('_i')); // 1 false
a.i = 2
console.log(a.i, a.hasOwnProperty('i')); // undefined false
console.log(a._i, a.hasOwnProperty('_i')); // 2 true
原型中存在setter已完全改变了写入a.i
时发生的事情。是否有任何其他语言功能可以更改访问属性时发生的情况?具体来说,除了存在setter之外,写操作总是直接更新对象吗?
答案 0 :(得分:0)
一个例外是如果您的对象是一个代理,它允许您拦截对该对象的所有属性调用,并获得被调用属性的名称。您也可以控制许多其他行为。所以你可以做到
const target = {};
const proxyHandler = {
set(target, property, value, receiver) {
//gets called on any setter operation
}
};
const proxy = new Proxy(original, proxyHandler );
此处还有更多内容:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy