Call, Apply, and Other Inheritance Functions
call
Call and apply are two functions that allow us to change what this
represents. This is why this
can be difficult to deal with in JavaScript.
Example 1:
var getAge = function(friend) {
return friend.age;
};
var john = { name: 'John', age: 21 };
getAge(john);
rewritten using call
var getAge = function() {
return this.age;
};
var john = { name: 'John', age: 21 };
getAge.call(john);
Example 2:
var setAge = function(friend, newAge) {
friend.age = newAge;
};
var john = { name: 'John', age: 21 };
setAge(john, 35);
rewritten using call
var setAge = function(newAge) {
this.age = newAge;
};
var john = { name: 'John', age: 21 };
setAge.call(john, 35);
apply
apply
works just like call
, but your second parameter is an array of objects instead of a comma separated list.
Going back to Example 2, here's what it would look like with apply
.
var setAge = function(newAge) {
this.age = newAge;
};
var john = { name: 'John', age: 21 };
setAge.apply(john, [35]);
Calling on a solution
Let's talk about using call
or apply
to set the this
context for a function before it is run.
function Person(name) {
this.name = name;
this.friends = [];
}
Person.prototype.addFriend = function(name) {
this.friends.push(new Person(name));
};
function Student(name, course) {
// masks all the constructor properties including name (as the second parameter)
Person.call(this, name);
this.course = course;
// If we wanted to, we could also use .apply like so:
// Person.apply(this, [name]);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
The code above is why we forgo talking about this
until now. In the context of event listener callbacks, this
refers to the DOM element that trigged the event. But here, this
can really be anything you want it to be.
Still confused? Understanding this
once and for all
Useful methods when working with inheritance
hasOwnProperty
Object.hasOwnProperty('nameOfProperty') - always make sure the name of the property is in quotes. Classes that inherit from other classes will also return true if the property is checked.
Example 1
var taco = {
food: 'taco'
}
taco.hasOwnProperty(food); // returns an error
taco.hasOwnProperty('food'); // returns true
Example 2 with inheritance
function Person(name) {
this.name = name
}
Person.prototype.greet = function() {
return 'Hello, my name is ' + this.name;
};
function Student(name, course) {
Person.call(this, name);
this.course = course;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
var person = new Person('Bob');
var student = new Student('Tom', 'WDI');
person.hasOwnProperty('name'); //returns true
student.hasOwnProperty('course'); //returns true
student.hasOwnProperty('name'); //returns true
instanceof
This method is a bit more common, and the syntax looks like this:
object instanceof Class
Example 1:
var color1 = {};
color1 instanceof Object; // returns true
Example 2 with inheritance
function Person(name) {
this.name = name
}
Person.prototype.greet = function() {
return 'Hello, my name is ' + this.name;
};
function Student(name, course) {
Person.call(this, name);
this.course = course;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
var p = new Person('Bob');
var s = new Student('Tom', 'WDI');
s instanceof Person //returns true
p instanceof Student //returns false
Person instanceof Object //returns true
String instanceof Object //returns true
Object instanceof Boolean //returns false
isPrototypeOf
This method is used a bit less frequently, but the syntax looks like this:
Object.prototype.isPrototypeOf(objectInstance);
Example:
var p = new Person('Bob');
var s = new Student('Tom', 'WDI');
Person.prototype.isPrototypeOf(s); // returns true
Student.prototype.isPrototypeOf(p); // returns false
You can read more about the difference between isPrototypeOf and isInstanceOf here