JavaScript属性查找规则有哪些例外?

时间:2017-10-09 12:37:54

标签: javascript inheritance prototype getter-setter

以下代码演示了"标准" 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之外,写操作总是直接更新对象吗?

1 个答案:

答案 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