Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi Level Inheritance in Javascript

I am trying to mock inheritance in Javascript using prototype.

I have a function named Model and a type of model => Item.

var Model = function() { 
   this.names = ["name1", "name2"]; 
} 
Model.prototype.Item = function(args) { 
   this.init = function(item_name) { 
      this.names[0] = item_name; // ERROR: Cannot set property '0' of undefined
   } 
}
var m = new Model();
var i = new m.Item();
i.init("New Name"); // ERROR: Cannot set property '0' of undefined

How can I access names array from init() function above?

like image 523
Nitin Avatar asked Jun 04 '14 19:06

Nitin


2 Answers

Inheritance in Javascript is tricky! Read this post for a great explanation of traditional object oriented inheritance in Javascript: http://blog.slaks.net/2013-09-03/traditional-inheritance-in-javascript/.

var Model = function () {
    this.names = ["name1", "name2"];
};

var Item = function () {
    //When inheriting in Javascript you must 
    //call the inherited function's constructor manually.
    Model.call(this);
};

//Inherit Model's prototype so you get all of Model's methods.
Item.prototype = Object.create(Model.prototype);
Item.prototype.constructor = Item;

Item.prototype.init = function (item_name) {
    this.names[0] = item_name;
};

var Employee = function () {
    Model.call(this);
};

Employee.prototype = Object.create(Model.prototype);
Employee.prototype.constructor = Employee;

var myItem = new Item();
myItem.init("New Name");
//prints New Name, name2
console.log(myItem.names);


var myEmployee = new Employee();
//prints name1, name2
console.log(myEmployee.names);

Analogous code in a more traditional object oriented language (C#):

public class Model
{
    public Model()
    {
        this.Names = new[] {"name1", "name2"};
    }
    public string[] Names { get; set; }
}

public class Item : Model
{
    public Item() : base() { }

    public void init(string item_name)
    {
        this.Names[0] = item_name;
    }
}

public class Employee : Model
{
    public Employee() : base() { }
}

var myItem = new Item();
myItem.init("New Name");
//prints New Name, name2
Console.WriteLine(String.Join(",", myItem.Names));

var myEmployee = new Employee();
//prints name1, name2
Console.WriteLine(String.Join(",", myEmployee.Names));
like image 145
Steven Wexler Avatar answered Oct 06 '22 21:10

Steven Wexler


The issue you're having is that in the second item Item, your reference to this has no idea about it's "parent" object Model.

One way to re-write this is like so:

var Model = function() { 
   this.names = ["name1", "name2"]; 
}

Model.prototype.init = function(item_name) {
    this.names[0] = item_name;
}
var Item = new Model();
Item.init("New Name");

console.log(i);

Fiddle here: http://jsfiddle.net/BksS3/1/

like image 41
kcent Avatar answered Oct 06 '22 21:10

kcent