【问题标题】:Hijacking .__proto__劫持 .__proto__
【发布时间】:2016-07-05 11:14:40
【问题描述】:

当一个对象被实例化时,无论是字符串/函数/等等,都会包含一个__proto__ 属性。该属性似乎是由Object.prototype 中的__proto__ 访问器生成的...

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;
    }
});

目前还不能确定它是否正常工作,但这只是一个尝试向您展示我想要实现的目标的示例。

【问题讨论】:

  • 包含__proto__ 属性” - 不,它是继承的。您不会说每个对象都包含hasOwnProperty 属性,对吗?
  • 不,你不能再劫持他们and that's a good thing

标签: javascript inheritance prototype proto


【解决方案1】:

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

没有。创建对象时不会调用 __proto__ 属性的访问器。仅当您获取或设置__proto__ 时才会调用它们。您可以通过查看the spec 来了解创建对象时会发生什么:

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 / setPrototypeOf on ObjectReflect。)另外请注意,并非所有对象都有 __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

【讨论】:

  • 我假设编译器在实例化对象时调用get __proto__
  • @LostInCyber​​Space:不,引擎在实例化对象时不会调用任何访问器。
猜你喜欢
  • 1970-01-01
  • 2011-10-03
  • 2011-09-22
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多