There are five cases that this refers to

This in the global context

In the global context, this refers to the window, which is simpler

this === window
Copy the code

This in the event-bound method

Bind a method to an element’s event behavior. When the event behavior is triggered, the method executes, and this in the method refers to the current element.

let body = document.body;
body.onclick=function(){
	console.log(this) // body
}
Copy the code

Here’s another example:

let body = document.body; Function (){console.log(this) // this points to window} body.onclick=function(){console.log(this) // body func()}Copy the code

Special case: In IE6-8, DOM2 event binding based on attachEvent implementation, event firing, method this pointing to window

body.attachEvent("onclick", function(){
	console.log(this)  // window
})
Copy the code

This in normal function execution

Function execution (including self-executing function execution, ordinary function execution, object member access call method execution, etc.), just need to see the function execution time before the method name., if there is,. This refers to whatever comes first, otherwise this refers to window (strictly undefined).

1. Self-executing function execution

(function(){console.log(this) // window, undefined))() let obj = {f: (function(){ console.log(this) // window return function(){} })() } obj.f()Copy the code

2. Ordinary function execution

Function func(){console.log(this) // this points to window} func()Copy the code

3, object member access call method execution

Function func(){console.log(this) // this points to the object that called it obj} let obj = {f:func} obj.f()Copy the code

The constructor this points to

This in the constructor body is an instance of the current class

Function Fun(){console.log(this) // this points to f} let f = new Fun()Copy the code

The arrow function this points to

The arrow function does not have this; it inherits this from its own context

Let obj = {fun: function(){console.log(this) // this points to the object calling it}, arrowFun: ()=>{console.log(this) // Arrow function has no this, This}} console.log(obj.fun()) // obj console.log(obj.arrowfun ()) // windowCopy the code

Forcing changes to this will not work either

Obj. Sum. Call (obj) // This still refers to windowCopy the code

Force this to refer to call, apply, bind

Each Function is an instance of the Function class. Function’s prototype has three methods: call, apply, and bind that can be used to change the reference to this. So what’s the difference between these three methods?

let obj = {
	name: "obj"
}
function func(x,y){
	console.log(this,x,y)
}
Copy the code

Call: * * [r]. The function call ((context), param1, param2,…).

The call method executes [function], refers this to [context], and passes parameters like param1 and param2 to the function, respectively.

Func. call(obj,1,2) // obj 1 2Copy the code

The first parameter is not passed or is passed null/undefined. In non-strict mode, this refers to window

Apply: [function]. Apply ([context], [param1, param2,… )

This is basically the same as call, except that the parameters passed to the function need to be passed to Apply as an array. Apply internally passes array entries to [function], so the result is the same as call.

Func. apply(obj,[1,2]) // obj 1 2Copy the code

Bind: [function]. Bind ((context), param1, param2,…).

Call is similar in syntax, but does not act the same as call/apply.

Call /apply immediately executes the current function and changes the “this” reference in the function. Bind does not execute the current function immediately, but preemptively points this to [context] and stores params. It is executed when it is called.

Bind (obj,1,2) // func does not call func() // obj 1,2Copy the code

Suppose you have a requirement to bind a func function to the body click event, requiring that when the body click event is triggered, func be executed with this in func pointing to obj.

body.onclick=func.bind(obj)
Copy the code

But the bind method is not compatible with IE6-8, so how can we do this without bind?

body.onclick=function(){
	func.call(obj)
}
Copy the code

We can achieve the same effect with call

Simple implementation of call, apply, bind

We have seen the use of call, apply, and bind and the differences between them.

Call method:

Function.prototype.myCall = function(target, ... Args) {// this is the function that calls myCall const func = this; // Call methods can only be used with function if (typeof this! = = "function") {throw new TypeError (" is not a function ")} / / in the absence of the value this point to the window let the context = target | | the window / / Let result = context.fn() let result = context.fn(... args) return result }; Function foo(x,y) {console.log(this.name, x,y)} foo.myCall(obj, 21, 30) // lp 21 30Copy the code

The apply method:

The only difference between Apply and Call is that apply takes only two arguments, the second of which is an array

Function. The prototype. MyApply = Function (target, args) {/ / this is the Function of call myApply const func = this; // Call methods can only be used with function if (typeof this! == "function") {throw new TypeError("not a function")} // If (! Array. IsArray (args)) {throw new TypeError (" not a Array ")} / / in the absence of the value this point to the window let the context = target | | the window / / Let result = context.fn() let result = context.fn(... args) return result };Copy the code

Bind: The only difference between bind and call is that bind returns a function and is not executed immediately. We can implement the bind method on top of call.

Function.prototype.myBind = function(context,... // this is the function that calls myBind const func = this; if (typeof this ! Throw new TypeError("not a function")} return () => { Keep this pointing to the same as this in bind this.myCall(context,... params) } }Copy the code