Consider the following snippet, here javascript prototypical inheritance is used to collect CSS properties from DOM elements. elem
array contains objects corresponding to DOM nodes, each object have a style
field, and each elem[x].style
is also an object. And elem[x].style
objects repeat DOM tree hierarchy, being connected through __proto__
. The rootStyle
variable serves as a root for all elem[x].style
prototype chains:
var rootStyle = {},
elem = [{}, {}, {}];
rootStyle.__proto__ = null;
rootStyle.fontSize = '14px';
elem[0].style = {};
elem[0].style.__proto__ = rootStyle;
elem[0].style.fontWeight = 'bold';
elem[0].className = 'my-elem-123';
elem[1].style = {};
elem[1].style.__proto__ = rootStyle;
elem[1].style.fontStyle = 'italic';
elem[1].className = 'my-elem-456';
elem[2].style = {};
elem[2].style.__proto__ = elem[1].style;
elem[2].style.textDecoration = 'underline';
elem[2].className = 'my-elem-789';
...
// later in the code
var cssCode = [],
i, len = 3;
for(i = 0; i < len; i++) {
cssCode.push('.' + elem[i].className + '{' + getCssRules(elem[i]) + '}';
}
function getCssRules(elem) {
var result = [],
cssProperty, cssValue;
for(cssProperty in elem.style) {
// No hasOwnProperty check!
// Here (and in for..in loop) happens the lookup magic that I need
cssValue = elem.style[cssProperty];
result.push(cssValue + ':' + cssProperty + ';';
}
return result;
}
And as said here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto, I should not change object's prototype because of performance impacts.
The object key-value lookup internally turns into many operations, but it's acceptable, it's a managed language anyway, and any operation here have an overhead. And if you don't make crazy depth prototype chains, then the speed of prototype chain lookup should be comparable to the speed of any "single step" operation, I mean, close to complexity of O(1). And if my algorythm naturally needs such data structure with exactly such behaviour, it's pain in the butt - to implement my own chain lookup, or some totally different solution, just because "setting __proto__
is bad".
So, what are the cases or good / bad usage of __proto__
?
What will happen if I store references to real DOM nodes in elem
array like this:
elem[0].domNode = document.body.childNodes[0];
elem[1].domNode = document.body.childNodes[1];
elem[2].domNode = elem[1].domNode.childNodes[0];
Is it good, bad or doesn't matter, to link objects with custom prototype chain, and objects with generic prototype chain, does the engine's optimization fail here ?
Added: Ok, now I get it all! All the confusing stuff with setting __proto__
is exactly about changing __proto__
reference. It triggers bad things (see link in the first comment). We really should stick with the syntax in the accepted answer. Firstly I thought, that bad things happen because of the empty prototype by itself, lacking some members, needed by javascript engine for optimizations.