1

实例化对象时,无论是字符串/函数/等,__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;
    }
});

无法判断它是否正常工作,但这只是一个尝试向您展示我想要实现的目标的示例。

4

1 回答 1

3

我想知道是否可以在__proto__实例化对象时劫持此属性以执行代码块。

__proto__不会。创建对象时不会调用属性的访问器。它们仅在您 get 或 set 时被调用__proto__。您可以通过查看规范来了解创建对象时会发生什么:

ObjectCreate ( proto [ , internalSlotsList ])

带有参数proto (一个对象或 null)的抽象操作 ObjectCreate用于指定新的普通对象的运行时创建。可选参数internalSlotsList是必须定义为对象一部分的附加内部插槽名称的列表。如果未提供列表,则使用新的空列表。此抽象操作执行以下步骤:

  1. 如果未提供 internalSlotsList,则让internalSlotsList新的空 List。
  2. obj是一个新创建的对象,在 internalSlotsList 中的每个名称都有一个内部插槽
  3. obj的基本内部方法设置为 9.1 中指定的默认普通对象定义。
  4. obj的 [[Prototype]] 内部槽设置为proto
  5. obj的 [[Extensible]] 内部槽设置为true
  6. 返回obj

回想一下,这__proto__ 不是对象的原型引用;那是[[Prototype]]对象中的插槽,在代码中无法访问。__proto__只是访问该插槽中值的一种(仅限网络)方法。(一般的方式,它也适用于浏览器之外,而__proto__官方没有,是getPrototypeOf/ setPrototypeOfonObjectReflect。)还要注意,并非所有对象都有__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

于 2016-07-05T11:17:54.907 回答