1

I am currently trying to create class inheritance using prototypes in javascript, and I understand how that works in the simple example below.

var Person = function(){
    var name = "Steve";
}

var Employee = function(){
    var company = "Stack Overflow";
}

Employee.prototype = new Person;

var employee1 = new Employee();

But now assume that I want to add parameters to the constructors so that I can set the values as I create the objects. So the updated code would look like this:

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    //How can I use initName to set the value in the prototype class?

    var company = initCompany;
}

Employee.prototype = new Person;

var employee1 = new Employee("Bob", "Intel");

How can I call into the Person constructor with the name? In C# (the language I'm most comfortable with), you would simply call the base constructor, and pass through the necessary parameters, but it doesn't seem like there is an equivalent pattern in javascript.

For reference, this is what it might look like in C#:

public class Person
{
    string name;

    public Person(string initName)
    {
        name = initName;
    }
}

public class Employee : Person
{
    string company;

    public Employee(string initName, string initCompany) : base(initName)
    {
        company = initCompany;
    }
}

var employee1 = new Employee("Bob", "Intel");

Disclaimer: As you can see, I am primarily a object oriented programmer, but I am currently working in javascript, so some of what I've asked may be non-sensical from a javascript perspective, feel free to challenge my presuppositions as necessary.

2
  • See this Questenter link description hereion. It has everything you are looking for Commented Oct 19, 2017 at 19:04
  • See this Answer. It has everything you are looking for. Commented Oct 19, 2017 at 19:06

2 Answers 2

3

JavaScript has real classes as of ES6. They won't work in older browsers (i.e. Internet Explorer), but you can write this as

class Person {
  constructor(name){
    this.name = name;
  }
}

class Employee extends Person {
  constructor(name, company) {
    super(name);
    this.company = company;
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, I wish I could just ignore older browsers and use this implementation, but unfortunately I have to support older versions of JS, so I can't use this. Is there a way to do the equivalent of this in an older version?
You can look at the babel repl and see what they're doing. It's not the prettiest, but it definitely does what you're looking for. babeljs.io/repl
Thanks, that's a useful tool. It is definitely messy under the covers, so I think I'll probably stick with Ananth's approach for now since it is a bit easier to maintain
1

Standard ES5 and below

For the specific case of your example, headmax's answer does what you need. However, what you're trying to do in a general sense (that is, classical inheritance) may be possible with C# and other languages with classical inheritance models, but it's not possible the same way with the JavaScript Prototype model. You can probably get closest to that using composition, like so:

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    var innerPerson = new Person(initName);

    var company = initCompany;
}

var employee1 = new Employee("Bob", "Intel");

Then, any addition functionality you would want to implement on the Employee class that mirrors or extends the Person class would have to be implemented as a passthrough, ie. call the corresponding function in the inner Person object. Admittedly, this is far from actual inheritance, but it can approximate the behavior for the sake of things like polymorphism.

EDIT

Well this is something I completely forgot about before, but you can actually achieve a bit more of inheritance behavior using call() or apply(). Using call or apply allows you to run a function (including object constructors) in a specified context, so you can run the parent's constructor in the context of the child, like this:

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    Person.call(this, initName);
    var innerPerson = new Person(initName);

    var company = initCompany;
}

var employee1 = new Employee("Bob", "Intel");

However, if you wanted to be able to access the name property inside the Employee constructor and any other functions you define inside Employee, you'd need to change name's scope visibility from var name = ... to this.name = ... so that it is visible in the scope of the object being constructed (which is what this refers to) as opposed to being bound to the scope of the constructor function. For great examples of all of this in use, see here.

ES6

With the adoption of ECMAScript 2015, you can now wrap your class definitions in syntactic sugar that looks a lot more like classical inheritance. But you have to remember that this is still implemented with prototypical inheritance under the hood, so likely there's something like composition or call()/apply() going on when the JavaScript engine actually executes the code or a transpiler like Babel rewrites it.

3 Comments

Ok, sounds like I may just not be able to do what I'm hoping to do, but thanks for the alternative approach of using composition. I'll have to go with that for now unless someone gives a better answer down the line. If they don't, then I'll mark yours as accepted tomorrow
Glad composition might help, but I updated the answer to include some other ways that may be useful and more like inheritance
Excellent! Using Person.call and removing the "var innerPerson" line, and changing the scope to all be "this..." instead of "var..." gets me much closer to what I want than any of the other approaches, and basically covers all of the behavior I want (especially because it allows me to overwrite functions and properties as desired in the child class)

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.