当对象被实例化时,无论是字符串/函数/等,都包含__proto__
属性。此属性似乎由__proto__
...
Object.prototype
访问者生成
Object.prototype == {
__defineGetter__ : __defineGetter__()
__defineSetter__ : __defineSetter__()
__lookupGetter__ : __lookupGetter__()
__lookupSetter__ : __lookupSetter__()
constructor : Object()
hasOwnProperty : hasOwnProperty()
isPrototypeOf : isPrototypeOf()
propertyIsEnumerable: propertyIsEnumerable()
toLocaleString : toLocaleString()
toString : toString()
valueOf : valueOf()
get __proto__ : __proto__() // getter
set __proto__ : __proto__() // setter
};
我想知道在实例化对象时是否有可能劫持此__proto__
属性来执行代码块。我们的想法是在调用原始访问者以在新实例上创建__proto__
之前,使用自定义属性替换__proto__
属性,该属性执行某些代码。
如果这是有道理的!如果不是这就是我要去的地方:
pro = Object.prototype;
tmp = {};
Object.defineProperty(tmp, '__proto__',
Object.getOwnPropertyDescriptor(pro, '__proto__')
);
delete pro.__proto__;
Object.defineProperty(pro, '__proto__',{
get:function(){
console.warn('intercepted Get __proto__');
return tmp.__proto__;
},
set(p){
console.warn('intercepted Set __proto__');
tmp.__proto__ = p;
}
});
无法判断它是否正常运行,但它只是一个例子,试图告诉你我想要实现的目标。
答案 0 :(得分:2)
我想知道在实例化对象时是否有可能劫持此
__proto__
属性来执行代码块。
没有。创建对象时不会调用__proto__
属性的访问者。只有在您获得或设置__proto__
时才会调用它们。您可以通过查看the spec:
ObjectCreate( proto [, internalSlotsList ])
带参数 proto (对象或null)的抽象操作ObjectCreate用于指定新普通对象的运行时创建。可选参数 internalSlotsList 是必须定义为对象一部分的其他内部插槽的名称列表。如果未提供列表,则使用新的空列表。此抽象操作执行以下步骤:
- 如果未提供 internalSlotsList ,请将 internalSlotsList 设为新的空列表。
- 让 obj 成为新创建的对象,其中 internalSlotsList 中的每个名称都有一个内部插槽。
- 将 obj 的基本内部方法设置为9.1中指定的默认普通对象定义。
- 将 obj 的[[Prototype]]内部插槽设置为 proto 。
- 将 obj 的[[Extensible]]内部插槽设为 true 。
- 返回 obj 。
醇>
回想一下,__proto__
不是对象的原型参考;那是对象中的[[Prototype]]
槽,在代码中无法访问。 __proto__
只是一种(仅限Web)访问该槽中值的方法。 (一般的方式,也适用于浏览器以外的__proto__
官方没有,getPrototypeOf
/ setPrototypeOf
位于Object
和Reflect
。)另请注意并非所有对象都有__proto__
,因为并非所有对象都继承自Object.prototype
:
var o1 = {};
console.log("__proto__" in o1); // true
var o2 = Object.create(null); // No prototype
console.log("__proto__" in o2); // false
var o3 = Object.create(o2); // Has a prototype, but still no link to Object.prototype
console.log("__proto__" in o3); // false