Approach of new Object methods in ES5

Asen Bozhilov asen.bozhilov at gmail.com
Sat Apr 17 12:34:24 PDT 2010


Erik Arvidsson wrote:
> Unfortunately there are use case (although limited) that cannot be 
> solved without a mutable __proto__. Extending built *classes* is one 
> such use case.
>
> function HelloElement() {
>   var el = document.createElement('div');
>   el.__proto__ = HelloElement.prototype;
>   el.text = 'Hello';
>   return el;
> }
> HelloElement.prototype = {
>   __proto__: HTMLDivElement.prototype,
>   set text(text) { this.textContent = text; },
>   say: function() {
>     alert('Hello');
>   }
> };
>
> document.body.appendChild(new HelloElement).say();
That design is used by some js libraries. Mutable __proto__ allow us to 
change prototype chain of created object and safe internal methods of 
that object. For example:

function f() {}
f.__proto__ = {
    __proto__ : Function.prototype
};

f(); //still have [[Call]] method
new f(); //still have [[Construct]] method

FuseJS use design like that for augment native objects. 
http://github.com/jdalton/fusejs
The author use factories, which create native objects and mutate 
__proto__ instead of augmentation directly created object. Lets suppose 
the follows factories:

var Factory = (function () {
    function object() {
        return {__proto__ : object.prototype};
    }
   
    object.prototype.augment = function() {
        //...
    };
   
    function array() {
        var arr = Array.apply([], arguments);
        arr.__proto__ = array.prototype;
        return arr;
    }
   
    array.prototype = {
        __proto__ : Array.prototype
    };
   
    return {
        object : object,
        array : array
    };
})();

var obj = Factory.object();
/*Augment created object with new properties*/
obj.augment({
    property1 : true,
    property2 : true,
    propertyN : true
});

var arr = Factory.array();
/*Augment created array with new properties*/
arr.augment({
    property1 : true,
    property2 : true,
    propertyN : true
}); //Type Error

Cannot be shared properties by object.prototype and array.prototype, 
because they are not in same prototype chain.  For generic methods you 
need copy reference in both object, which is not good. Of course that 
design is a little bit step forward instead of augmentation, which is 
used by some libraries.

Another  benefit  from mutable __proto__ is opportunity to operate only 
with own properties. For example if you want shallow copy of some object 
you can use: 

function clone(obj) {
    var copy = {__proto__ : obj.__proto__};
    obj.__proto__ = {__proto__ : null};
    for (var i in obj) {
        copy[i] = obj[i];
    }
    obj.__proto__ = copy.__proto__;
    return obj;
}





More information about the es-discuss mailing list