Scope of this
In browser or node?
this can have different reference depending on the environment. If you're on Firefox, this references to window object. If you're on node.js, this references to global object.
console.log(this);
function logThis() {
console.log(this);
}
logThis(); // they're the same2
3
4
5
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> console.log(this);
<ref *1> Object [global] {
global: [Circular *1],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
queueMicrotask: [Function: queueMicrotask],
structuredClone: [Getter/Setter],
atob: [Getter/Setter],
btoa: [Getter/Setter],
performance: [Getter/Setter],
fetch: [Function: fetch],
crypto: [Getter]
}
undefined
>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Object Literal
this references the object using function keyword or function literal .
WARNING
However arrow function does not! this inside a arrow function reads the closest execution context(when strict mode off).
const person = {
fullName: null,
age: 0,
withFullName: function(fullName) {
this.fullName = fullName;
return this;
},
withAge(age) {
this.age = age;
return this;
},
withGender: (gender) => {
this.gender = gender // `this` is global or window, will eventually throw
return this;
}
}
// no error
person.withFullName('John Smith').withAge(30);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const person = {
fullName: null,
age: 0,
withFullName: fullName => {
this.fullName = fullName;
return this;
},
withAge: age => {
this.age = age;
return this;
}
}
person.withFullName('John Smith').withAge(30);2
3
4
5
6
7
8
9
10
11
12
13
Binding this to an object
Function.bind
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg An object to which the this keyword can refer inside the new function.
* @param argArray A list of arguments to be passed to the new function.
*/
bind(this: Function, thisArg: any, ...argArray: any[]): any;2
3
4
5
6
7
Function.bind re-targets this to the the given thisArgs
const person = {
fullName: null,
age: 0,
withFullName: function(fullName) {
this.fullName = fullName;
return this;
},
withAge: function(age) {
this.age = age;
return this;
}
}
function withGender(gender) {
this.gender = gender;
return this;
}
const bindWithPerson = withGender.bind(person.withFullName('John Smith').withAge(30), 'male');
console.log(bindWithPerson().gender) // male2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Function.call and Function.apply
/**
* Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.
* @param thisArg The object to be used as the this object.
* @param argArray A set of arguments to be passed to the function.
*/
apply(this: Function, thisArg: any, argArray?: any): any;
/**
* Calls a method of an object, substituting another object for the current object.
* @param thisArg The object to be used as the current object.
* @param argArray A list of arguments to be passed to the method.
*/
call(this: Function, thisArg: any, ...argArray: any[]): any;2
3
4
5
6
7
8
9
10
11
12
13
Instead of returning a new function using Function.bind, use Function.call
const personWithGender = withGender.call(person, 'male');
// or
const personWithGender = withGender.apply(person, ['male']);2
3
TIP
Function.call is prefered as choice for modern javascript since it takes variadic parameter.
constructor
Using function as constructor with new operator, it creates a new object and auto bound this to this new object.
function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person('John Smith', 30);2
3
4
5
6
use strict
ES5 introduced strict mode that disallow this targeting global or window object. For most web framework, strict mode is enabled by default.
'use strict'
const f = () => {
console.log(this); // undefined
}2
3
4
5