1

When an object is instantiated, be it a string/function/etc, a __proto__ property is included. This property seems to be generated by the __proto__ accessors in 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
};

I'm wondering if it is possible to hijack this __proto__ property to execute a code block when an object is instantiated. The idea being to replace the __proto__ property with a custom property that executes some code before calling the original accessors to create the __proto__ on the new instance.

If that makes sense! If not here's where I'm up to:

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

Can't tell if it works properly yet but it's only an example to try and show you what I'm trying to achieve.

LostInCyberSpace
  • 413
  • 4
  • 19
  • "*a `__proto__` property is included*" - well, no, it's **inherited**. You wouldn't say that a `hasOwnProperty` property is included in every object, would you? – Bergi Jul 05 '16 at 11:52
  • No, you cannot hijack them *any more*, [and that's a good thing](http://stackoverflow.com/a/13040748/1048572). – Bergi Jul 05 '16 at 11:53

1 Answers1

3

I'm wondering if it is possible to hijack this __proto__ property to execute a code block when an object is instantiated.

No. The __proto__ property's accessors aren't called when the object is created. They're only called when you get or set __proto__. You can see what happens when an object is created by looking at the spec:

ObjectCreate (proto [ , internalSlotsList ])

The abstract operation ObjectCreate with argument proto (an object or null) is used to specify the runtime creation of new ordinary objects. The optional argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, a new empty List is used. This abstract operation performs the following steps:

  1. If internalSlotsList was not provided, let internalSlotsList be a new empty List.
  2. Let obj be a newly created object with an internal slot for each name in internalSlotsList.
  3. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  4. Set the [[Prototype]] internal slot of obj to proto.
  5. Set the [[Extensible]] internal slot of obj to true.
  6. Return obj.

Recall that __proto__ isn't the object's prototype reference; that's the [[Prototype]] slot in the object, which isn't accessible in code. __proto__ is just a (web-only) means of accessing the value in that slot. (The general way, which also works outside browsers whereas __proto__ officially doesn't, is getPrototypeOf / setPrototypeOf on Object and Reflect.) Also note that not all objects have __proto__ because not all objects inherit from 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
Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875