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