Skip to content Skip to sidebar Skip to footer

How Do I Call An Inherited Javascript Constructor With Parameters?

Greetings, After reading the following article I have a question: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript In the inheritance example, the Perso

Solution 1:

Well, a way that you can re-use the logic of the Person constructor is invoking it with call or apply, for example:

functionPerson(gender) {
  this.gender = gender;
}

functionStudent(gender) {
  Person.apply(this, arguments);
}
Student.prototype = newPerson(); // make Student inherit from a Person objectStudent.prototype.constructor = Student; // fix constructor propertyvar foo = newStudent('male');
foo.gender;             // "male"
foo instanceofStudent; // true
foo instanceofPerson;  // true

If you want to prevent the execution of the Person constructor when is called without arguments (like in the line: Student.prototype = new Person();), you can detect it, e.g.:

functionPerson(gender) {
  if (arguments.length == 0) return; // don't do anythingthis.gender = gender;
}

Solution 2:

Accepted answer seems to be incorrect. Based on what Mozilla says about OO JavaScript, correct way to do it is:

varPerson = function(firstName) {
    this.firstName = firstName;
};

functionStudent(firstName, subject) {
  // Call the parent constructor, making sure (using Function#call)// that "this" is set correctly during the callPerson.call(this, firstName);

  // Initialize our Student-specific propertiesthis.subject = subject;
};

// Create a Student.prototype object that inherits from Person.prototype.// Note: A common error here is to use "new Person()" to create the// Student.prototype. That's incorrect for several reasons, not least // that we don't have anything to give Person for the "firstName" // argument. The correct place to call Person is above, where we call // it from Student.Student.prototype = Object.create(Person.prototype); // See note below// Set the "constructor" property to refer to StudentStudent.prototype.constructor = Student;

// Example usage:var student1 = newStudent("Janet", "Applied Physics");

As you can clearly see, Mozilla specifies that it is a common error to use "new Person()" to create the Student.prototype. Hence accepted answer is misleading.

I have actually tested this in my ongoing project and Mozilla's way is correct, while above answer does not work.

Solution 3:

// define the Person ClassfunctionPerson(name) {
    this.personname = name;
}

Person.prototype.walk = function(){};
Person.prototype.sayHello = function(){
  alert (this.personname );
};

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor


The full code:

<script>// define the Person ClassfunctionPerson(name) {
    this.personname = name;
}

Person.prototype.walk = function(){};
Person.prototype.sayHello = function(){
  alert (this.personname );
};

// define the Student classfunctionStudent() {}

// inherit PersonStudent.prototype = newPerson("test");

// correct the constructor pointer because it points to PersonStudent.prototype.constructor = Student;

// replace the sayHello methodStudent.prototype.sayHello = function(){
  alert('hi, I am a student and my name is \'' + this.personname + '\'' );
}

// add sayGoodBye methodStudent.prototype.sayGoodBye = function(){
  alert('goodBye');
}

var student1 = newStudent();
student1.sayHello();
student1.sayGoodBye();
</script>

Solution 4:

By all other comments I created an example which works for me. Since I did not use prototype explicitly I hope I am not missing an important point.

// variable for tracking instantiations and checking the uniqueness of the objectsvar instances = 0;

var Generic = function() {
    this.instanceId = ++instances;
    this.toString = function() {return'Generic [iid='+ this.instanceId +']'};
    console.log('constructor-invoke: Generic ('+ this.instanceId +')');
};

var SpecificName = function(inName) {
    Generic.call(this);
    this.getName = function() { return inName; };       
    var superToString = this.toString.bind(this); // binds the inner function 'this' to this SpecificName instancethis.toString = function() {
        return'SpecificName [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']'
    }
    console.log('constructor-invoke: SpecificName ('+ this.instanceId +')');
};

var SpecificNames = function(inFirstName, inLastName) {
    SpecificName.call(this, inLastName +', '+ inFirstName );
    var superToString = this.toString.bind(this);
    this.toString = function() {
        return'SpecificNames [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']'
    }
    console.log('constructor-invoke: SpecificNames ('+ this.instanceId +')');
};

var g = new Generic(); 
var sn = new SpecificName('Run Forest Run');
var sns = new SpecificNames('Forest','Gump');

console.log('g:   '+ g.toString());
console.log('sn:  '+ sn.toString());
console.log('sns: '+ sns.toString());

leads to this output:

constructor-invoke: Generic (1)
constructor-invoke: Generic (2)
constructor-invoke: SpecificName (2)
constructor-invoke: Generic (3)
constructor-invoke: SpecificName (3)
constructor-invoke: SpecificNames (3)
g:   Generic [iid=1]
sn:  SpecificName [iid=2, name=Run Forest Run, super.toString=Generic [iid=2]]
sns: SpecificNames [iid=3, name=Gump, Forest, super.toString=SpecificName [iid=3, name=Gump, Forest, super.toString=Generic [iid=3]]]

Post a Comment for "How Do I Call An Inherited Javascript Constructor With Parameters?"