Question

So every mention of __proto__ is usually followed by a reference to Brendan Eich's plea not to use it. I've been playing around with some reflection in Typescript, navigating the prototype chain of a class down to a provided ancestor class using it, and would love to inject a single prototype property holding class metadata.

Does anyone have any specifics on the performance overhead I might incur, or a solution that doesn't rely on __proto__?

EDIT - Updated with code. This is just a contrived example I typed out but it illustrates what I'm hoping to do. I'm not quite sure how to benchmark the percieved slowdown caused by __proto__ mutation. But I gave it a shot anyways. Instantiation, prototype property access and method calls execute no differently given the modification.

class Base {
    public getClassName() : string {
        return this['_className'] || undefined;
    }
}

class Intermediate extends Base {   
}

class Final extends Intermediate {  
}

function traverseProtoChain(derivedClass, baseClass) {
    var cursor = derivedClass.prototype;
    while (cursor instanceof baseClass) {
        if (isDefined(cursor.constructor)) {
            var className = getProtoName(cursor);
            if (isValidString(className)) 
                cursor['_className'] = getProtoName(cursor);
        }           

        if (isDefined(cursor.__proto__)) {
            cursor = cursor.__proto__;
        }   
    }   
}
Was it helpful?

Solution

You can use the ECMAScript 5.1 standard:

Object.getPrototypeOf(cursor)

For really quite old versions of browsers, you could attempt to fall back to __proto__ if Object.getPrototypeOf doesn't exist, but you can decide if those browsers are important given your specific context.

Here is an example that shows this. bar.prototype doesn't work, because it is an instance. getPrototypeOf works and gives you the same answer as the discouraged __proto__.

class Foo {
    constructor(name: string) {

    }
}

class Bar extends Foo {

}

var bar = new Bar('x');

console.log(bar.prototype);
console.log(Object.getPrototypeOf(bar));
console.log(bar.__proto__);

So you could write the "pleases everyone"...

if (Object.getPrototypeOf) {
    console.log(Object.getPrototypeOf(bar));
} else if (bar.__proto__) {
    console.log(bar.__proto__);
}

Final curve-ball... __proto__ is likely to become standardised in ECMAScript 6... worth bearing in mind!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top