6

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?

11
  • This line should be failing var i = new Model.Item();. Did you mean (new Model).Item() or new Model().Item()? Commented Jun 4, 2014 at 19:48
  • Sorry, copy & paste issue. It is m.Item() Commented Jun 4, 2014 at 19:50
  • 2
    put a Console.log(this) in the Item constructor. You'll see this refers to a new object created when you call new m.Item(), not the object created wheny ou call new Model(). You've implemented Item as a separate class that happens to be an attribute on the Model prototype object, not an inherited class. Sub classes do not have access to properties in their parent classes. Commented Jun 4, 2014 at 19:53
  • 1
    What inheritance do you want? Do you want Model to inherit from Item? Commented Jun 4, 2014 at 19:55
  • 2
    ...you don't need to "mock" inheritance in JavaScript. You just need to learn how idiomatic JavaScript inheritance works. Commented Jun 4, 2014 at 19:57

5 Answers 5

11

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));
Sign up to request clarification or add additional context in comments.

4 Comments

@StevenWexler Would that be stupid If in the original question var m = new Model(); is placed before Model.prototype.Item =.. & subsequently this.names[0] be replaced by m.names[0]? Im trying to understand the right thing to do
You're correct. You should define how Model works before you use it.
@StevenWexler so it wont still be a bad OOP practice if done that way?
You should do what you claim is "stupid" if you want to follow good OOP practices.
1

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/

Comments

0

As far as making this work is concerned, this would work too.

var Model = function() { 
   this.names = ["name1", "name2"]; 
} 
Model.prototype.Item = function(args) { 
   this.init = function(item_name) { 
      this.names[0] = item_name;
   } 
}
var m = new Model();
var i = new m.Item();
i.init.apply(m,["New Name"]); 

Comments

0

Manager class object will access all method from Person and Employee. Multilevel Inheritance example

      function Person(firstName,lastName,marks,age,gender) 
     {
      this.firstName = firstName;
      this.lastName = lastName;
      this.age=age;
      this.gender=gender;
     }

      Person.prototype.getFullname = function()
       {
         console.log("Full Name is "+this.firstName +' '+this.lastName);
       }

 function Employee(firstName,lastName, marks, rollno, salary) 
 {

     Person.call(this,firstName,lastName,marks, rollno, salary);
     this.rollno = rollno;
     this.salary=salary;


  }

  function Manager(firstName,lastName, marks, rollno, salary, code) {

      Employee.call(this, firstName,lastName,marks, rollno, salary, code);

      this.code = code;
  }



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

Employee.prototype.getSalary = function()
       {
         console.log(`Salary of ${this.firstName} ${this.lastName} is ${this.salary}`);
       }


Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.designation = function() {
      console.log("You'r designation is Manager");
  }
var m = new Manager("shankar","singh", 21,100, 40000,"CS12");

 console.log(m);
   m.getFullname();
   m.getSalary();
    m.designation();


</script>

Comments

0
    This is how you implement multi-level inheritance in JavaScript.

<script> 
    //Multi Level Inheritance Example
    //Parent Class
    class A{
        constructor()
        {

            this.a=0;       
        }
        setA()
        {
            this.a=10;
        }
    }
    //Child Class
    class B extends A{
        constructor()
        {
            super();//call parent class constructor
            this.b=0;
        }
        setB()
        {
            this.b=20;
        }
    }
    class Addition extends B{
        add()
        {       
            this.setA();
            this.setB();
            return this.a+this.b;
        }
    }
    class Print extends Addition{
        print()
        {
            var result=this.add();
            document.write("<br/>a="+this.a);
            document.write("<br/>b="+this.b);
            document.write("<br/>Addition="+result);
            
                
        }
    }
    //Make Object
    let obj=new Print();
    obj.print();
    /*
    Assignment:
    Make subtraction, multiplication, diuvision classes and print the output as

    ==============
    Two Digit Calculator
    ==============
    a=10
    b=20;
    Addition=30
    Subtraction=-10
    Multiplication=200
    Division:.5

    */
    </script>




Comments

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.