3

I'm trying to fully understand how 'extend' works in javascript.

Here's a simple extend function I found on google

function extend(child, parent) {

    var f = function() {}
    f.prototype = parent.prototype;


    var i;

    for( i in parent.prototype ) {
        child.prototype[i] = parent.prototype[i];
    }


    child.prototype.constructor = child;
    child.parent = parent;

}

it works, but I don't understand "child.prototype.constructor = child" part. The function still works without it.

What's the purpose of the line?

Moon
  • 22,195
  • 68
  • 188
  • 269
  • 1
    This seems to be wrong. Are you sure that it is not `child.prototype = new f;` instead of that loop? – Bergi Aug 29 '12 at 18:17
  • @Bergi // actually I modified it a little bit. Yes, there was child.prototype = new f; I changed ti to for(i in parent.prototype).. instead. It still deosn't explain me why I need to do "child.prototype.constructor = child" – Moon Aug 29 '12 at 18:51
  • 1
    So why did you do that? This change makes the questioned line useless. – Bergi Aug 29 '12 at 18:54

4 Answers4

2

No. Where did you find that? It mixes two approaches:

The classical prototype inheritance

function inherit(child, parent) {
    var f = function() {}
    f.prototype = parent.prototype;

    child.prototype = new f();
    child.prototype.constructor = child;
}

This function creates a new object that inherits directly from the prototype object of the parent function. It is an old-style synonym for Object.create(). With that, a prototype chain is set up - all instances of child inherit from the parent.prototype as well. Because a new object is generated to overwrite child.prototype, the "constrcutor" property needs to be updated.

The mixin inheritance

This function just loops over all properties of the parent's prototype object, and copies them onto the child's prototype object. This is quite what the common helper function extend does. It does not reset the "prototype" property of the child function, but it also does not set up a inheritance chain.

function extend(child, parent) {
    for (var i in parent.prototype ) {
        child.prototype[i] = parent.prototype[i];
    }
}

You are right, the line

child.prototype.constructor = child;

is quite useless here - the "constructor" property is not enumerable and will not be affected by the extend.

Also, your function sets a "parent" property of the child function object to the parent function, which is not required:

child.parent = parent;
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • // I'm not sure if you're still looking at this post or not, but I have a question. Base on the inherit() code, multiple inheritance will not work. Do you know how to make it work for multiple inheritance? I can't think of anything, but mixin. – Moon Aug 30 '12 at 23:14
1

It appears to me that the 'child.prototype.constructor' is a base/vanilla implementation of the object, it allows other objects to extend from it without inheriting the same parent. Hence why it is declared prior to 'child.parent = parent'.

trickyzter
  • 1,591
  • 13
  • 9
  • no. `constructor` is just a property, nothing more. What do you mean by "extend from it without inheriting the same parent"? – Bergi Aug 29 '12 at 19:21
1

This may not directly answer your question, but I would like to reccomend you to use the extend implementation of John Resig:

It allows you to create a constructor named init, like this:

var MyClass = Class.extend({
    init: function() {
         console.log("Running a constructor");
    }
});

and instanciate objects like this (normal):

var obj = new MyClass();
Andreas Åkre Solberg
  • 1,705
  • 12
  • 11
0

This example shows how to inherit a class in javascript

var a = function(){
    // class a constructor
    this.a_priviligiate_var = 1;
}
a.prototype.a_public_var = 2;
var b = function(){
    // class b constructor
    // super call of class a constructor
    // this line makes b class to inherit all privileged vars
    b.prototype.constructor.call(this)
    this.b_priviligiate_var = 3;
}
b.prototype.b_public_var = 4;
b.prototype = new a();
var c = new b();

Defining a claas:

var a = function(){
    // class a constructor
    this.a_priviligiate_var = 1;
}
a.prototype.a_public_var = 2;

Defining another class:

var b = function(){
    // class b constructor
    // super call of class a constructor
    // this line makes b class to inherit all privileged vars
    b.prototype.constructor.call(this)
    this.b_priviligiate_var = 3;
}
b.prototype.b_public_var = 4;

Setting the super(parent) class. This line copies all b.prototype

b.prototype = new a();

Creating a instance of c

var c = new b();
cuzzea
  • 1,515
  • 11
  • 22
  • what do you mean by 'proper'? and what's your example?? – Moon Aug 29 '12 at 17:56
  • Javascript is a prototypal language so its just plain wrong to talk of classes. – Christoph Aug 29 '12 at 18:40
  • ...and also, the examples are wrong. `b.call(this)` would be enough, instead of creating new instances (including properties) `Object.create(a.prototype)` should be used, you set the `b_public_var` before overwriting the whole object, and (last but no least) there is nothing like "priviligiate variables"! – Bergi Aug 29 '12 at 19:26
  • @Christoph - this is a long conversation about classes in js and it is too long to talk about it here – cuzzea Aug 29 '12 at 21:32
  • @Bergi - :) that is how it is called, the priviligiate variables can access the private vars in the "class" definition, check this fiddle: http://jsfiddle.net/sZmLz/ – cuzzea Aug 29 '12 at 21:38
  • You are mixing quite a lot of things up here. Javascript has no privacy paradigm. There are neither private vars nor privileged vars... It's object properties which are always visible (or public in terms of "classical" speaking) and variables with finite lifetime because they are limited to the function scope. You should take some time and read about prototypal languages. – Christoph Aug 30 '12 at 06:41
  • P.s. And sure, prototypal languages can mimic classical behaviour while vice versa classical ones can't. – Christoph Aug 30 '12 at 06:46
  • 1
    @cuzzea: There are *privileged methods* that can access *local* ("private") *variables* in the constructors scope. Methods on the prototype can only access public *properties*. – Bergi Aug 30 '12 at 10:15