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 same
2
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) // male
2
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