I apply inheritance in JavaScript in following way:
var employee = function(name) {
this.name = name;
}
employee.prototype.getName = function() {
return this.name;
}
var pEmployee = function(salary) {
this.salary = salary;
}
pEmployee.prototype.getSalary = function() {
return this.salary;
}
var employee = new employee("mark");
pEmployee.prototype = employee;
var pe = new pEmployee(5000);
console.log(pe.getName());
console.log(pe.getSalary());
but it showing following error in console:
Uncaught TypeError: pe.getSalary is not a function
Could any one tell me what's the reason behind this error?
It's because you've added getSalary to the object pEmployee.prototype refers to, but then completely replaced pEmployee.prototype with a new object. So naturally the new object doesn't have getSalary.
What you've shown isn't the correct way to set up inheritance in ES5 and earlier. Instead, see inline comments:
var Employee = function(name) {
this.name = name;
};
Employee.prototype.getName = function() {
return this.name;
};
var PEmployee = function(name, salary) {
// Note call to superclass
Employee.call(this, name);
// Now this level's initialization
this.salary = salary;
};
// This sets up inheritance between PEmployee.prototype and
// Employee prototype (then fixes up the
// constructor property)
PEmployee.prototype = Object.create(Employee.prototype);
PEmployee.prototype.constructor = PEmployee;
// NOW you add the method
PEmployee.prototype.getSalary = function() {
return this.salary;
};
// Usage
var employee = new Employee();
var pe = new PEmployee("Mark", 5000);
console.log(pe.getName());
console.log(pe.getSalary());
See my answer here for a more thorough example, and also what it would look like if you used ES2015's class syntax instead.
Related
What are the details why pe.getName() is working and pe.getSalary() is not?
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
var employee = new Employee("Mark");
PermanentEmployee.prototype = employee;
var pe = new PermanentEmployee(5000);
document.write(pe.getName());
document.write(pe.getSalary());
By doing this later in your code
PermanentEmployee.prototype = employee;
you might override this
PermanentEmployee.prototype.getSalary = function()
Try this instead:
function Employee(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
function PermanentEmployee(name, annualSalary) {
Employee.call(this, name); // calling parent's "constructor"
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype = Object.create(Employee.prototype); // setting "inheritance"
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
var pe = new PermanentEmployee("Mark", 5000);
console.log(pe.getName());
console.log(pe.getSalary());
This is actually the expected behavior. If you want to understand why, here we go...
Consider the following schema, available in the excellent book Exploring ES6 by Dr. Axel Rauschmayer.
Before to go on, here is an important rule: in JavaScript, when you create an instance of a "class", this instance will reference the prototype property of its constructor through its dunder proto (__proto__ or [[Prototype]]).
Top left
In your example, Employee and PermanentEmployee are constructor functions. Like any function in JavaScript, they are instances of Function and they use Function.prototype.
var Employee = function(name) {
this.name = name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
console.log(typeof Object.getPrototypeOf(Employee)); // ES5
console.log(typeof PermanentEmployee.__proto__); // ES6
console.log(Object.getPrototypeOf(Employee).constructor); // ES5
console.log(PermanentEmployee.__proto__.constructor); // ES6
Top right
When you write Employee.prototype.getName or PermanentEmployee.prototype.getSalary, you are actually adding new properties to the prototype property of Employee and PermanentEmployee. But Employee.prototype and PermanentEmployee.prototype are instances of Object and use Object.prototype.
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
console.log(typeof Employee.prototype);
console.log(typeof PermanentEmployee.prototype);
console.log(Employee.prototype);
console.log(PermanentEmployee.prototype);
Since PermanentEmployee.prototype is a simple object, this is not reasonable to do so: PermanentEmployee.prototype = employee.
When you do that, you override the prototype. To make a basic comparison, look at this example with an object literal:
var obj = {
foo: 'Foo'
};
obj.bar = 'Bar';
console.log(obj);
obj = 'Baz';
console.log(obj);
obj = {
foo: 'Foo',
bar: 'Bar',
baz: 'Baz'
};
console.log(obj);
You should keep this in mind when you play with prototypes...
Bottom right
In JavaScript, there are several strategies to create a "pure" object (functions and arrays are objects too...). You can:
Use an object literal: {}
Use a constructor: new Object()
Use Object.create()
In your example, you are using constructors. Therefore, your instances will use the prototype properties of your constructors, which themselves use the prototype property of Object. This is how the prototype chain works!
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
var employee = new Employee("Mark");
console.log(Object.getPrototypeOf(employee)); // ES5
console.log(employee.__proto__.constructor); // ES6
console.log(Object.getPrototypeOf(Object.getPrototypeOf(employee))); // ES5
console.log(employee.__proto__.__proto__.constructor); // ES6
But of course, if you have completely overriden your prototype somewhere, you break the prototype chain and it will not work as expected...
<script>
var Employee = new function(name)
{
this.name=name;
}
Employee.prototype.getName = function()
{
return this.name;
}
var PermanenetEmployee = new function(annualsalary)
{
this.annualsalary=annualsalary;
}
var employee = new Employee("rahul");
PermanenetEmployee.prototype = employee;
var pe = new PermanenetEmployee(5001);
document.write(pe.getName());
</script>
i am implementing inheritance in java script. From this code i want to print employee name like "rahul".But i am getting error in this like Uncaught TypeError: Cannot set property 'getName' of undefined(anonymous function).How to resolve this error?
Employee.prototype.getName = function()
{
return this.name;
}
This is the problem:
var Employee = new function(name)
// ------------^^^
{
this.name=name;
}
(And the same for PermanenetEmployee.)
You don't want new there. new calls the function. You want to do that later, as you have when assigning to employee.
Note that the way you're setting up inheritance between them is an anti-pattern. To make PermanenetEmployee correctly "subclass" Employee, do this:
PermanenetEmployee.prototype = Object.create(Employee.prototype);
PermanenetEmployee.prototype.constructor = PermanenetEmployee;
not
var employee = new Employee("rahul");
PermanenetEmployee.prototype = employee;
...and then have PermanenetEmployee accept name and pass it to Employee:
var PermanenetEmployee = function(name, annualsalary) {
Employee.all(this, name); // <====
// ...
};
...or better use, use ES2015 ("ES6") class (transpiling if you need to, for instance with Babel).
Here's a correct setup. I've also fixed the typo in PermanenetEmployee:
var Employee = function(name) {
this.name = name;
};
Employee.prototype.getName = function() {
return this.name;
};
var PermanentEmployee = function(name, annualSalary) {
Employee.call(this, name);
this.annualSalary = annualSalary;
};
// Set up subclass
PermanentEmployee.prototype = Object.create(Employee.prototype);
PermanentEmployee.prototype.constructor = PermanentEmployee.prototype;
PermanentEmployee.prototype.getAnnualSalary = function() {
return this.annualSalary;
};
// Using
var pe = new PermanentEmployee("Rahul", 5001);
console.log(pe.getName());
console.log(pe.getAnnualSalary());
And with ES2015:
class Employee {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class PermanentEmployee extends Employee {
constructor(name, annualSalary) {
super(name);
this.annualSalary = annualSalary;
}
getAnnualSalary() {
return this.annualSalary;
}
}
// Using
var pe = new PermanentEmployee("Rahul", 5001);
console.log(pe.getName());
console.log(pe.getAnnualSalary());
Again, note that you need to transpile if you want to use that syntax in the wild (for now).
There are a couple ways you can get inheritance to work in JS, I am using this pattern.
First declare the base prototype:
Employee = function () {
};
Employee.prototype = {
getName: function () {}
};
And then the prototype that inherits the base:
PermanentEmployee = function () {
Employee.call(this);
};
PermanentEmployee.prototype = Object.create(Employee.prototype);
PermanentEmployee.constructor = PermanentEmployee;
PermanentEmployee.prototype.foo = function() {}
How do you access the this object from another object instance?
var containerObj = {
Person: function(name){
this.name = name;
}
}
containerObj.Person.prototype.Bag = function(color){
this.color = color;
}
containerObj.Person.prototype.Bag.getOwnerName(){
return name; //I would like to access the name property of this instance of Person
}
var me = new Person("Asif");
var myBag = new me.Bag("black");
myBag.getOwnerName()// Want the method to return Asif
Don't put the constructor on the prototype of another class. Use a factory pattern:
function Person(name) {
this.name = name;
}
Person.prototype.makeBag = function(color) {
return new Bag(color, this);
};
function Bag(color, owner) {
this.color = color;
this.owner = owner;
}
Bag.prototype.getOwnerName = function() {
return this.owner.name;
};
var me = new Person("Asif");
var myBag = me.makeBag("black");
myBag.getOwnerName() // "Asif"
Related patterns to deal with this problem: Prototype for private sub-methods, Javascript - Is it a bad idea to use function constructors within closures?
I've been trying to get RequireJS set up to handle circular dependencies using the special 'exports' magic module as recommended by James Burke's answer to this question.
Following the example given by #jrburke in that question:
define("Employee", ["exports", "Company"], function(Company) {
function Employee(name) {
this.name = name;
this.company = new Company.Company(name + "'s own company");
};
exports.Employee = Employee;
});
define("Company", ["exports", "Employee"], function(Employee) {
function Company(name) {
this.name = name;
this.employees = [];
};
Company.prototype.addEmployee = function(name) {
var employee = new Employee.Employee(name);
this.employees.push(employee);
employee.company = this;
};
exports.Company = Company;
});
jsfiddle
The problem is that using his own example, the exports module is undefined, and therefore exports.Employee and exports.Company don't set. If I try to include exports as an argument of the define callback functions, it simply initializes in both cases as empty and does not carry the constructor functions it was assigned.
What am I doing wrong?
EDIT: Through trial and error, I got the above code working at: http://jsfiddle.net/jpk45vow/4/. Can anyone explain why it works, because it makes no sense to me.
Edit: I couldn't find more info about the magic exports method. I could, however, mimic its intended behavior with a dummy "Container" module. See it in this fiddle: http://jsfiddle.net/amenadiel/a7thxz98/
console.log("start");
define("Container",function() {
var Container={};
return Container;
});
define("Employee", ["Container"], function(Container) {
var Employee= function(name) {
this.name = name;
this.company = new Container.Company(name + "'s own company");
};
Container.Employee = Employee;
});
define("Company", ["Container"], function(Container) {
var Company=function(name) {
this.name = name;
this.employees = [];
};
Company.prototype.addEmployee = function(name) {
var employee = new Container.Employee(name);
this.employees.push(employee);
employee.company = this;
};
Container.Company = Company;
});
define("main", ["Container","Employee","Company" ], function ( Container) {
var john = new Container.Employee("John");
var bigCorp = new Container.Company("Big Corp");
bigCorp.addEmployee("Mary");
console.log(bigCorp);
});
require(["main"]);
I have the inheritance chain Vehicle -> Motorized -> Car implemented:
function Vehicle()
{
var m_name;
this.setName = function(pName) {
m_name = pName;
};
this.getName = function() {
return m_name;
};
}
function Motorized()
{
var m_started = false;
this.start = function() {
m_started = true;
console.log(getName() + " started");
};
}
function Car()
{ }
//set up the inheritance chain
Motorized.prototype = new Vehicle();
Car.prototype = new Motorized();
// use
var lCar = new Car;
lCar.setName("Focus");
console.log(lCar.getName()); // Focus
lCar.start(); // ReferenceError: getName is not defined
When I invoke lCar.start() (defined in function Motorized), I get an ReferenceError: getName is not defined. How can I use the inherted method getName() in my subclass Motorized?
Because Javascript doesn't know where to look for your getName() method. You can clarify the syntax declaring a self variable that always points to the right object, like this:
function Vehicle()
{
var self = this; // Vehicle
var m_name;
this.setName = function(pName) {
self.m_name = pName;
};
this.getName = function() {
return self.m_name;
};
}
function Motorized()
{
var self = this; // Motorized
var m_started = false;
this.start = function() {
/*
`self` is Motorized, with proto Vehicle, so
has a getName() method.
`this` instead is the object where you call
start() from, i.e. Car, in the example down below.
*/
self.m_started = true;
console.log(self.getName() + " started");
};
}
function Car()
{ }
//set up the inheritance chain
Motorized.prototype = new Vehicle();
Car.prototype = new Motorized();
// use
var lCar = new Car;
lCar.setName("Focus");
console.log(lCar.getName()); // Focus
lCar.start(); // Focus started
Note that in this case, using the keyword this instead of self throughout the code would have worked as well, but you definitely cannot omit it before getName(). Also, if you are planning to add more code later on, such as event handlers in jQuery, having a clear reference to the class you're coding in can be useful, as this can become easily ambiguous, at least from the human point of view.
Anyway, whether using self is a bad coding pattern or not is the topic of this question; the point in your example is that you need to call self.getName() or this.getName().