0

I'm looking to simplify inheritance in Javascript a bit. From what I've gathered so far, a good way to achieve "inheritance" between "classes" is as follows:

function ParentClass() {
    //Parent Constructor
}

ChildClass.prototype = new ParentClass(); //Step 1: Use parent as prototype
ChildClass.prototype.constructor = ChildClass; //Step 2: Designate appropriate constructor
function ChildClass() {
    ParentClass.call(this, arguments); //Step 3: Call the parent's constructor from the child's

    //Child Constructor
}

I like to divide the process into three "steps" as I labeled above (Step 1, 2 and 3). I would like to put all three of these steps into one function (coming from a Java background, I've labeled it "extend") that I can call from the function constructor object, like so:

function ParentClass() {
    //Parent Constructor
}

ChildClass.extend(ParentClass); //Execute steps 1, 2 and 3 all in this function
function ChildClass() {
    //Child Constructor
}

This is what I have so far:

Function.prototype.extend = function (parent) {
    var oldConstructor = this.prototype.constructor;
    this.prototype = new parent(); //Step 1
    this.prototype.constructor = function (arguments) { //Step 2
        parent.apply(this, arguments); //Step 3
        oldConstructor(arguments);
    };
}

Steps 1 and 2 of the extend function work fine in this context, but Step 3 is giving me issues. What I am attempting to do is replace the Child's constructor function with a new function that calls the parent Constructor, and then the Child's constructor. However when I run this the parent constructor is not being called. I haven't been able to nail down the problem (am I using the "this" keyword correctly?); perhaps I am approaching this the wrong way. It is possible to make a function that does this, right? How can I make a working "extend" function?

UPDATE:

The real problems seems to lie with my use of the "this" keyword. Here is the code I am looking at now:

function ParentClass(x) {
    this.value = x;
}

function ChildClass() {
}
ChildClass.extend(ParentClass);


function testtest() {
    var a = new ParentClass("hello world"); //Alerts "hello world"
    alert(a.value);
    var b = new ChildClass("hello world"); //Alerts "undefined"
    alert(b.value);
}

Why does the first alert work and second does not? I thought that "this" refers to the context in which a function is running, which in both cases would be the object calling the constructor (a or b).

2
  • I just tried your extend function out and the parent constructor is being called. Can you give an example where it is not working for you? Commented Mar 21, 2013 at 20:03
  • The problem seems to lie with the "this" keyword. Properties are being set in my parent constructor (this.x = y), but those properties don't apply to the Child object instance. All functions are being called, but the properties are not being set as I expected. Commented Mar 23, 2013 at 22:11

2 Answers 2

2

If you really want to do this, perhaps you should just use Coffeescript. Or at least get some ideas from it.

It provides support for classes and inheritance transparently on top of Javascript, and does it using pretty much the same ideas you are using here.

If this is an academic exercise, by all means go ahead (and check out how Coffeescript does it for ideas). But otherwise, there's no need to reinvent the wheel.

For a direct comparison, paste the following into http://js2coffee.org/

class Shape
  area: -> undefined
  name: -> "Shape"

class Rectangle extends Shape
  constructor: (w, h) ->
    @w = w
    @h = h

  area: ->
    @w * @h

  name: -> "Rectangle" + super

A Rectangle's name() would now return RectangleShape. The name thing is silly, but gets you an idea of how super works.

What it looks like in JS (note all the plumbing in the __extends function):

var Rectangle, Shape,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

Shape = (function() {

  function Shape() {}

  Shape.prototype.area = function() {
    return void 0;
  };

  Shape.prototype.name = function() {
    return "Shape";
  };

  return Shape;

})();

Rectangle = (function(_super) {

  __extends(Rectangle, _super);

  function Rectangle(w, h) {
    this.w = w;
    this.h = h;
  }

  Rectangle.prototype.area = function() {
    return this.w * this.h;
  };

  Rectangle.prototype.name = function() {
    return "Rectangle" + Rectangle.__super__.name.apply(this, arguments);
  };

  return Rectangle;

})(Shape);
Sign up to request clarification or add additional context in comments.

1 Comment

The __extends function seems to be more or less what I am trying to accomplish; with a little bit of adaptation I can use it just like I would have used my own extend() function. Thank you!
1

Noticed that the code in your 2nd block does not execute the steps in the same order. When you declare the function after calling extend, it overrides the constructor that is created by the extend function. Try declaring your child class first, and then extending it:

This works for me:

function Parent() {
  console.log("Parent Constructor");
}

function Child() {
  console.log("Child Constructor");
}

Child.extend(Parent);

new Child()

Outputs:

Parent Constructor
Child Constructor

1 Comment

Both constructors will actually be called regardless of the order of "extend()" and the function declaration. Thank you for the help though. I worded my question wrongly and I've now updated it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.