我一直认为,当一个对象调用[[set]]
(或者它是[[put]]
?时,引擎总是将属性分配(或尝试)到该对象,而不管它是什么原型。
但今天我试过这个
parent={
set num(v){
alert();
}
}
obj=Object.create(parent);
obj.num=123;
它调用了setter,那么当引擎设置属性时会发生什么?它是否遍历原型链以检查它是否首先有任何setter?
答案 0 :(得分:3)
引擎执行它始终执行的操作,即首先在实例上查找属性,然后在实例中查找原型链中的属性。如果使用setter定义属性(无论在何处找到并定义),则执行setter。在您的情况下,它在原型父级中找到该属性,并执行setter,显示警报。实际上没有设置。 (当然,如果未使用setter定义属性,则在实例上设置该值。)
如果要在实例本身上使用相同的名称实际创建属性,可以使用defineProperty
(或Object.create
的第二个参数)来实现。此属性将在原型上以相同名称“隐藏”(隐藏)该属性。下次尝试设置属性时,引擎将在实例上找到该属性,并在那里设置它(除非您在实例上定义的属性也有一个setter,在这种情况下将调用setter)。 p>
请注意,setter本身不进行任何设置。无论你想做什么设置,你都必须自己做。例如,您可能希望通过_num
来设置代理属性,例如this._num = v
。显然,this
这里是实例 - 即使在原型上定义了setter - 因此_num
属性将在实例上。如果你试图在setter中做this.num = v
,你将得到一个无限循环,因为那将再次调用相同的setter。 num
不能同时是基于getter / setter和普通值属性的属性。
请考虑以下事项:
parent = { set num(v) { alert(v); } };
obj = Object.create(parent);
obj.num = 44; // alert
obj2 = Object.create(parent, { num: { value: 55 } });
obj2.num = 99 // proto ignored, no alert, simple assignment