sunwukung
sunwukung

Reputation: 2815

clone or apply : which is "better"?

I want to create a series of objects that inherit or copy instance properties from a base object. This has led me to a decision about which pattern to use, and I wanted to ask your opinions about which method was "better".

//APPLY:
// ---------------------------------------------------------
//base object template
var base = function(){
   this.x = { foo: 'bar'};
   this.do = function(){return this.x;}
}

//instance constructor
var instConstructor = function (a,b,c){
   base.apply(this);//coerces context on base
   this.aa = a;
   this.bb = b;
   this.cc = c;
}

instConstructor.prototype = new base();

var inst = function(a,b,c){
    return new instConstructor(a,b,c);
}

//CLONE   
// --------------------------------------------------------- 
function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}    

var x = {foo: 'bar'};

function instC(a,b,c){
     this.aa = a;
     this.bb = b;
     this.cc = c;
     this.x = clone(x);
};

instC.prototype.do = function(){
    return this.x;
}

they both achieve the same thing, namely unique instance properties based on a common template - the question is which one is more "elegant"

Upvotes: 3

Views: 82

Answers (2)

sunwukung
sunwukung

Reputation: 2815

OK, so i've given this some further thought - and the answer stems from the use case. Where clone is copying properties into a given scope, apply is changing the scope surrounding the property. The former is better for mixins, the latter for inheritance.

Upvotes: 0

hugomg
hugomg

Reputation: 69954

By the sound of your questions it looks like you are looking for something akin to Object.create. This function can be used to create a new object that has an object of your choice as a prototype.

//for old browsers without Object.create:
var objCreate = function(proto){
    function F(){};
    F.prototype = proto;
    return new F();

As for the comparison with the clone method, they do different things so you have to choose what is more appropriate.

Using prototypes will reflect changes on the parent object on the child objects.

a = {x:1};
b = Object.create(a);
a.x = 2;
//b.x is now 2 as well

You also have to be careful about using methods that have this. Depending on what you do you can have unwanted consequences if you use too much prototypal inheritance.

a ={
   x: 1,
   foo: function(){ this.x += 1 }
}
b = Object.create(a);
b.foo();
//a.x does not change

On the other hand, cloning clones stuff so you can be sure that the objects won't interfere with each other in any way. Sometimes this is what you want.

Upvotes: 2

Related Questions