This blog post looks at the special property __proto__, which allows you to get and set the prototype of an object. In order to understand this post, you should be familiar with JavaScript’s prototypal inheritance [1].
> var myProto = {};
> var obj = Object.create(myProto);
> Object.getPrototypeOf(obj) === myProto
true
__proto__ (pronounced “dunder proto”, from “double underscore” [2]) first appeared in Firefox and is an alias for [[Prototype]]. Using __proto__, the above code becomes:
> var myProto = {};
> var obj = { __proto__: myProto };
> obj.__proto__ === myProto
true
The following also holds:
> obj.__proto__ === Object.getPrototypeOf(obj)
true
Once it appeared in Firefox, __proto__ proved so popular that it is now also supported by V8 (Chrome, Node.js) and Nitro (Safari). As of ECMAScript 5, it is still non-standard, but due to its popularity, it will become part of ECMAScript 6.
Object.getPrototypeOf({ __proto__: null }) === null
function escapeKey(key) {
// We need to escape "__proto__", including the
// (n times) escaped version of it, to avoid clashes
if (key.indexOf("__proto__") === 0) {
return key+"%";
} else {
return key;
}
}
Obviously, you have to escape keys for both read and write access. Thus, you never need to un-escape.
var obj = {
__proto__: myProto,
foo: 123,
bar: "abc"
};
With Object.create(), you have two, equally unappealing, alternatives:
// Alternative 1: create empty object, assign
var obj = Object.create(myProto);
obj.foo = 123;
obj.bar = "abc";
// Alternative 2: property descriptors
var obj = Object.create(myProto, {
foo: {
value: 123,
writable: true,
enumerable: true,
configurable: true
},
bar: {
value: "abc",
writable: true,
enumerable: true,
configurable: true
}
});
var MyArrayProto = Object.create(Array.prototype);
MyArrayProto.foo = function (...) { ... };
function createMyArray() {
var arr = Array.prototype.slice.call(arguments);
arr.__proto__ = MyArrayProto;
}
var myarr = createMyArray();
It is not yet certain that you’ll also be able to change the prototype of an existing object via __proto__. The most important use case for that is to subtype Array, which can be better supported by other means, e.g. via a function Array.createArray(proto).
Lastly, ECMAScript 6 will probably also provide ways for switching off __proto__ for some objects, possibly even for all objects.