Michael Carper
Michael Carper

Reputation: 331

How to combine constructor function and prototype property

I'm trying to get a handle on how prototypes work. I have this example:

function Person(name) {
    if (arguments.length > 0)
        this.init(name);
}

Person.prototype.init = function(name) {
    this.name = name();
}
Employee.prototype = new Person();

function Employee (name, id) {
    if (arguments.length > 0) {
        this.init(name);
        this.id = id;
     }
}

var employee = new Employee("frank",01);
alert(employee.name);//returns frank

I'd trying to figure out how to combine the first two sections, and assign the "init" property within the function constructor. I have this, but it doesn't return anything:

function Person(name) {
    if (arguments.length > 0)
        this.init = function(name) {
    this.name = name;
        }
}
Employee.prototype = new Person();

function Employee (name, id) {
    if (arguments.length > 0) {
        this.init(name);
        this.id = id;
     }
}

var employee = new Employee("frank",01);
alert(employee.name);//returns nothing

I'm assuming I'm doing something wrong in the assigning of init, but I don't know what. Changing the initial property to

this.init(name) = function(name) {

doesn't work either.

Upvotes: 0

Views: 1083

Answers (2)

treeno
treeno

Reputation: 2600

Do you want to pass the init-property name from Employee to Person?

This is done like so:

// Create a constructor-function for your Person-Object.
function Person(name) {
    this.name = name;
}

// Create the constructor-function for an Employee-Object that extends Person
function Employee(name) {
   // Call the constructor-function from Person
   Person.call(this, name);
}

// Let the prototype of Employee be Person.prototype (Employee extends Person)
Employee.prototype = Object.create(Person.prototype);
// By changing the prototype of Employee we have lost our constructor-function Employee()
// so we have to recover it.
Employee.prototype.constructor = Employee;

Maybe you expect that the super-constructor will be called implicitly like you may know it from other languages like Java. But this doesn't happen in JavaScript. You have to do that on your own by calling

Person.call(this, name)

There is a very good JavaScript-Tutorial on MDN that helped me a lot to understand the prototype-stuff:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

Take a look at the chapter "Custom Objects". I think I couldn't explain it better.

Upvotes: 2

boobl
boobl

Reputation: 225

In your second code snippet, if you changed one line slightly

Employee.prototype = new Person('bob');

the code would've worked (the Employee still being 'frank')

The problem is in your constructor

function Person(name) {
    // create member 'init' ONLY if an argument was passed to the constructor
    if (arguments.length > 0)
        this.init = function(name) {
            this.name = name;
        }
}

As it was said in another answer, changing prototype of Person changes all instances of class Person, and

Person.prototype.init = function(name) { ... }

creates a member function init in every instance of Person. But in your constructor there is a condition, where init will be created only if there was an argument.

The line

Employee.prototype = new Person();

states, that every instance of class Employee will have all members, that has an object on the right side. In this case - a new instance of Person

By the way, it is not recommended to define function members inside class constructors, because every time the constructor will be called, a new function will need to be created. Whereas in case of modifying prototype, the function is created once, and shared with all instances of an object.

Upvotes: 1

Related Questions