Reputation: 8695
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.talk = function () {
return this.firstName + " " + this.lastName;
}
//creating a Person object for extension
var manager = new Person('jon', 'doe');
console.log(manager.talk());
//Manager prototype..but doesn't inherit Person methods
function Manager(firstName, lastName, accessCode) {
//shared properties
this.firstName = firstName;
this.lastName = lastName;
this.accesscode = accessCode;
}
function personChecker(person) {
var returnCode = 0;
if (person instanceof Person) {
returnCode = 1;
}
else if (person instanceof Manager) {
returnCode = 2;
}
return returnCode;
}
console.log(personChecker(manager));
Is it possible to share a prototype and have a different constructor? I would like to have Manager inherit everything from Person (and then extend it) and have a function switch on the prototype and do something different depending on the argument passed to the personChecker
function
Upvotes: 1
Views: 245
Reputation: 6414
The typical way to support this inheritance:
// create a blank function to pass the prototype
var blank = function() {};
// assign the prototype to inherit to the blank constructor
blank.prototype = Person.prototype;
// pass an instance of the prototype as the Manager prototype
Manager.prototype = new blank();
var person = new Person('John', 'Doe');
var manager = new Manager('Greg', 'Smith', 'access1234');
manager.talk(); // Greg Smith
person.talk(); // John Doe
Here is a fiddle: http://jsfiddle.net/XF28r/
Note a Manager is also a Person so you need to switch the check around.
function personChecker(person) {
var returnCode = 0;
if (person instanceof Manager) {
returnCode = 2;
} else if (person instanceof Person) {
returnCode = 1;
}
return returnCode;
}
Although note I would put this in a helper method:
function extend(parent, child) {
var blank = function() {};
blank.prototype = parent.prototype;
child.prototype = new blank();
}
So then you can simply use it:
extend(Person, Manager);
As Bergi has mentioned in the comments, this can also be reduced down to:
function extend(parent, child) {
child.prototype = Object.create(parent.prototype);
}
(works IE 9 upward)
Upvotes: 2
Reputation: 76766
In JavaScript, inheritance is generally done like this:
Manager.prototype = Object.create(Person.prototype);
Object.create
creates a new object with the object passed as the first argument in its prototype chain.
If you need to support old browsers that don't have Object.create
, you can do the "prototype dance" instead:
function F(){}
F.prototype = Person.prototype;
Manager.prototype = new F();
In any case, avoid code calling the constructor to get such an object (Manager.prototype = new Person()
), this is a well-known antipattern and will break as soon as your constructor relies on any of its arguments (and it causes other, more subtle problems).
Upvotes: 2
Reputation: 288530
Use the following:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.talk = function () {
return this.firstName + " " + this.lastName;
}
function Manager(firstName, lastName, accessCode) {
//shared properties
this.firstName = firstName;
this.lastName = lastName;
this.accesscode = accessCode;
}
Manager.prototype = new Person('jon', 'doe');
function personChecker(person) {
var returnCode = 0;
if (person instanceof Manager) {
returnCode = 2;
}
else if (person instanceof Person) {
returnCode = 1;
}
return returnCode;
}
Note that I have changed the order of the conditionals, because an instance of Manager
is an instance of Person
too:
var per = new Person('A', 'B');
per.talk(); // 'A B'
per instanceof Person; // true
per instanceof Manager; // false
personChecker(per); // 1
var man = new Manager('A', 'B');
man.talk(); // 'A B'
man instanceof Person; // true !!!!
man instanceof Manager; // true !!!!
personChecker(man); // 2
If you want to do it the good way, instead of
Manager.prototype = new Person('jon', 'doe');
use
Manager.prototype = Object.create(Person.prototype, {constructor: {value: Manager}});
but it doesn't work on old browsers.
Upvotes: 1