This is a basic question that we often use in our work and will be asked frequently in the interview.
This article will make a comprehensive summary of the direction of this. If there is something wrong, please point it out.
First, global execution
1. Non-strict mode
In the browser, this points to window
console.log(this); // window
Copy the code
2. Strict mode
In strict mode this refers to undefined
"use strict";
console.log(this); // undefined
Copy the code
Of course, the interviewer may confuse you by saying:
var a = 1
function fn() {
var a = 2
console.log(this.a) // console what ?
}
fn()
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- get -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Var a = 1 -> let a = 1;
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- get -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
var b = 1
function outer () {
var b = 2
function inner () {
console.log(this.b) // console what ?
}
inner()
}
outer()
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- get -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
const obj = {
a: 1.fn: function() {
console.log(this.a)
}
}
obj.fn() // console what ?
const f = obj.fn
f() // console what ?
Copy the code
Execute as an object method
- The call method isObject.method (), in the method
this
Point to this object. That is, who calls who.
var obj = {
name:'aaa'.hello3(){
console.log('HELLO3 this:'.this); // obj
}
}
obj.hello3(); // obj
Copy the code
- If you assign a method of an object to a variable and then call that method using that variable,
this
Point to thewindow
.
var obj = {
name:'aaa'.hello3(){
console.log('HELLO3 this:'.this); // obj}}var func = obj.hello3;
func(); // window
Copy the code
exercises
function fn () {
console.log(this.a)
}
const obj = {
a: 1
}
obj.fn = fn
obj.fn() // console what ?
Copy the code
function fn () {
console.log(this.a)
}
const obj1 = {
a: 1,
fn
}
const obj2 = {
a: 2,
obj1
}
obj2.obj1.fn() // console what ?
Copy the code
Sometimes interviewers ask about boundary cases such as implicit binding failures (listing) :
// The first is the case mentioned earlier
const obj1 = {
a: 1.fn: function() {
console.log(this.a)
}
}
const fn1 = obj1.fn Function fn1() {console.log(this.a)} function fn1() {console.log(this.a)}
fn1() // So this is actually the default binding rule, and the environment of the function 'fn1' is the global environment
// The second kind of setTimeout
setTimeout(obj1.fn, 1000) // The execution environment here is also global
// The third function is passed as an argument
function run(fn) {
fn()
}
run(obj1.fn) // A reference is passed in
// The fourth kind of generic anonymous function also points to the global
var name = 'The Window';
var obj = {
name: 'My obj'.getName: function() {
return function() { // This is an anonymous function
console.log(this.name)
};
}
}
obj.getName()()
// The fifth function assignment will also change the "this" pointer
// The sixth IIFE
Copy the code
Three, timer internal execution
Both setTimeOut and this inside setInterVal refer to the window
setTimeout(() = >{
console.log(this); // window
},2000)
Copy the code
The constructor is executed internally
The constructor call uses new, so this in the constructor refers to the object out of the constructor instance.
function Person(name){
this.name = name
console.log(this)}var p1 = new Person('yunxi'); // Person
Copy the code
If the constructor returns an object, this refers to that object.
function foo(a) {
this.a = a
}
const f = new foo(2)
f.a // console what?
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- get -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
function bar(a) {
this.a = a
return {
a: 100}}const b = new bar(3)
b.a // console what ?
Copy the code
Arrow function
The arrow function’s this is defined according to the context function.
1. This refers to window/undefined when the arrow function has no function context, i.e. when called directly
var obj = {
a: 100.hello5:() = >{
console.log(this.a)
}
}
obj.hello5(); // undefined
Copy the code
2. This refers to this of the context function when the arrow function has the context function environment. The arrow function’s this is the same as hello6’s this, since obj2 calls Hello6.
var obj2 = {
a: 100.hello6:function(){
var a = 200;
setTimeOut(() = >{
console.log(this.a)
},2000)
}
}
obj2.hello6(); / / 100
Copy the code
The arrow function itself does not have this; it inherits the outer layer
function fn() {
return {
b: () = > {
console.log(this)
}
}
}
fn().b() // console what?
fn().b.bind(1) ()// console what?
fn.bind(2)().b.bind(3) ()// console what?
Copy the code
B: Call, apply, bind
Use call, apply, and bind to change the direction of this. (Arrow function this will not be modified)
1. How to call
(1) The first argument to call is this. If the first argument is passed null, this is not changed.
(2) Call can pass multiple parameters
function fn(){
console.log(this)}var obj = {
a: 100
}
fn.call(obj); // {a:100}
fn.call(obj,[1.2].true, {},false)
Copy the code
2
Apply accepts only two parameters:
(1) The first argument is this. If the first argument is passed null, this is not changed.
The second argument must be an array.
function fn(){
console.log(this)}var obj = {
a: 100
}
fn.apply(obj); // {a:100}
fn.apply(obj,[1.2.4])
Copy the code
3. The use of the bind
(1) Bind will not be executed immediately.
(2) The first argument to bind is this. If the first argument is null, this is not changed.
(3) Bind only the value of the first bind.
(4) Bind can pass multiple parameters.
function fn(){
console.log(this)}var obj = {
a: 100
}
fn.bind(obj)(); // {a:100}
fn.bind(1).bind(2) ();/ / 1
Copy the code
Conclusion:
Similarities: Bind, call, and apply can change the direction of this, where the first argument accepted is this. If the first argument is passed null, the reference to this will not change.
Differences: 1. Bind does not execute immediately, while apply and call execute immediately. 2. The difference between apply and call is that apply can only take two arguments and the second argument must be an array, while Call can take many arguments and has no type restriction.
7. Priority
All of these methods must be in order, so when you’re acting on a function at the same time, which one does it take? It depends on the priority
// Implicit vs default -> Conclusion: implicit > default
function fn() {
console.log(this)}const obj = {
fn
}
obj.fn() // what ?
// Explicit vs implicit -> Conclusion: explicit > implicit
obj.fn.bind(5) ()// what ?
// new vs explicit -> conclusion: new > explicit
function foo (a) {
this.a = a
}
const obj1 = {}
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a) // what ?
// new
var baz = new bar(3)
console.log( obj1.a ) // what ?
console.log( baz.a ) // what ?
// Arrow function without this, comparison is meaningless
Copy the code
Priority New Bind > Explicit Bind > Implicit Bind > Default Bind
8. Exercises
/ / 1.
function foo() {
console.log( this.a ) // console what
}
var a = 2;
(function(){
"use strict" // I'm not going to get itfoo(); }) ();/ / 2.
var name="the window"
var object={
name:"My Object".getName: function(){
return this.name
}
}
object.getName() // console what ?
(object.getName)() // console what ?
(object.getName = object.getName)() // console what ?
(object.getName, object.getName)() // console what ?
/ / 3.
var x = 3
var obj3 = {
x: 1.getX: function() {
var x = 5
return function() {
return this.x
}(); / / ⚠ ️}}console.log(obj3.getX()) // console what?
/ / 4.
function a(x){
this.x = x
return this
}
var x = a(5) // Try again with let instead
var y = a(6) // Replace let with var, but remove y and try again
console.log(x.x) // console what ?
console.log(y.x) // console what ?
/ / equivalent to the
window.x = 5;
window.x = window;
window.x = 6;
window.y = window;
console.log(x.x) // void 0 executes Number(6).x
console.log(y.x) / / 6
Copy the code