In the first part of the series, we saw how object constructors could be used to create objects:
// Create Pet class. function Pet (name, ageInYears) { this.name = name this.ageInYears = ageInYears } // Add a method to the Pet class. Pet.prototype.notification = function () { return this.name + ' is ' + this.ageInYears + ' years old.' } // Create a new pet object. var dog = new Pet('Dog', 4)
This is what happens when you call the notification
function of
dog
:
// Returns 'Dog is 4 years old.' console.log(dog.notification())
In this case, this.name
is dog
’s name
('Dog'
) and this.ageInYears
is dog
’s age
in years (4
). this
basically refers to the newly
created dog
object, which is the object on the left of the dot.
One unexpected behavior of using this
when a method is called,
occurs when a called method is assigned to a variable. One solution would be to
use the Function.prototype.bind()
method (introduced in ES5) to
return the expected value.
function bindExample () { this.value = 'unexpected' var exampleObject = { value: 'expected', getValue: function () { return this.value } } // Returns 'expected'. console.log(exampleObject.getValue()) // Assign the 'getValue' method to //'notBoundMethod' variable. var notBoundMethod = exampleObject.getValue // Returns 'unexpected'. 'this.value' was supposed to be // 'expected' because of 'exampleObject.getValue'. console.log(notBoundMethod()) // 'this' refers to the global/window // object in the browser (so it looks at: // this.value = 'unexpected') console.log(this) // One solution would be to use 'Function.prototype.bind()'. // Bind the method and assign to 'boundMethod' variable. var boundMethod = exampleObject.getValue.bind(exampleObject) // Returns 'expected'. console.log(boundMethod()) } bindExample()
A callback function is a function passed into another function as an argument, which is then called in an outer function.
The object constructor below, creates Pet
objects where their
age
can be assigned. There is also a callback called
growUp
. If this
is used within that it would refer to
the global object or outer scope, which is not what we want. The code below will
not increase the age
of our pet fish
over time.
function Pet () { this.age = 0 setInterval(function growUp () { this.age++ // 'this' refers to the (global) object // where 'new Pet()' is called. console.log(this) // Returns NaN, NaN, NaN ... console.log(this.age) }, 1000) } var fish = new Pet()
Binding this
would fix this problem.
function Pet () { this.age = 0 setInterval(function growUp () { this.age++ // Now 'this' refers to 'fish'. console.log(this) // Returns 1, 2, 3 ... console.log(this.age) }.bind(this), 1000) } var fish = new Pet()
Arrow functions (introduced in ES6), do not have their own this
.
The this
object of the outer scope is used. Just pretend that the
arrow function does not exist when thinking about this
with arrow
functions. See the example below:
function Pet () { this.age = 0 setInterval(() => { this.age++ // Now 'this' refers to 'cat'. console.log(this) // Returns 1, 2, 3 ... console.log(this.age) }, 1000) } var cat = new Pet()
In the next part of the series, we will go over the class
keyword (introduced in ES6):
Object-oriented Programming in JavaScript (Part 3)
Back:
Object-oriented Programming in JavaScript (Part 1)
The first version of this article was originally published on medium:
https://medium.com/@wlwlz/object-oriented-programming-in-javascript-part-2-41c7e5e58a0b