Why change this point? How do bind, call, apply change the direction

We know that bind, call, and apply are all used to change this point, so why change this point? Please see the following example:

var name="lucy";
let obj={
    
    
 name:"martin",
 say:function () {
    
    
 console.log(this.name);
 }
};

obj.say(); //martin,this指向obj对象
setTimeout(obj.say,0); //lucy,this指向window对象

It can be observed that under normal circumstances, the this in the say method points to the obj object that called it, and the this in the say method in the timer setTimeout points to the window object (in the browser). This is because the say method is in The timer is executed as a callback function, so when returning to the main stack to execute, it is executed in the environment of the global execution context, but what we need is that this in the say method points to the obj object, so we need to modify the this point.

  • apply method

apply accepts two parameters, the first parameter is the pointer to this, the second parameter is the parameter accepted by the function, passed in in the form of an array, and when the first parameter is null or undefined, it points to window by default (in In the browser), the original function will be executed immediately after using the apply method to change the this point, and this method only temporarily changes the thi point once.

Daily usage: change this point

Example:

The callback function binds this to:

var name="martin";
var obj={
    
    
 name:"lucy",
 say:function(year,place){
    
    
 console.log(this.name+" is "+year+" born from "+place);
 }
};
var say=obj.say;
setTimeout(function(){
    
    
 say.apply(obj,["1996","China"])
} ,0); //lucy is 1996 born from China,this改变指向了obj
say("1996""China") //martin is 1996 born from China,this指向window,说明apply只是临时改变一次this指向

Tips: change the parameter input method

Example:

Find the maximum value in the array:

var arr=[1,10,5,8,3];
console.log(Math.max.apply(null, arr)); //10

The parameter of the Math.max function is a parameter list, such as: Math.max(1,10,5,8,3) is passed in, so we can't directly use the array as a parameter, but the apply method can use the array The parameters are converted into list parameters and passed in, so as to directly find the maximum value of the array.

  • call method

The first parameter of the call method is also the point of this, and what is passed in later is a parameter list (note the difference between passing parameters and apply). When a parameter is null or undefined, it points to window (in the browser). Like apply, call only temporarily changes this point and executes it immediately.

Example:

var arr=[1,10,5,8,3];
console.log(Math.max.call(null,arr[0],arr[1],arr[2],arr[3],arr[4])); //10

Accept is passed in as a parameter list, and apply is passed in as a parameter array.

  • bind method

The bind method is very similar to call. The first parameter is also the point of this, and the parameter list passed in later is also a parameter list (but this parameter list can be passed in multiple times, and call must pass in all parameters at once), but it changes this It will not be executed immediately after pointing, but will return a function that permanently changes the this point.

Example:

var arr=[1,10,5,8,12];
var max=Math.max.bind(null,arr[0],arr[1],arr[2],arr[3])
console.log(max(arr[4])); //12,分两次传参

It can be seen that the bind method can pass parameters multiple times, and finally all the parameters will be connected together and put into the function to run when the function runs.

Implement the bind method (interview questions):

Simple version

Function.prototype.bind=function () {
    
    
 var _this=this;
 var context=arguments[0];
 var arg=[].slice.call(arguments,1);
 return function(){
    
    
 arg=[].concat.apply(arg,arguments);
 _this.apply(context,arg);
 }
 };

Perfect version

//实现bind方法
 Function.prototype.bind = function(oThis) {
    
    
 if (typeof this !== 'function') {
    
    
 // closest thing possible to the ECMAScript 5
 // internal IsCallable function
 throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
 }
 var aArgs = Array.prototype.slice.call(arguments, 1),
 fToBind = this,
 fNOP = function() {
    
    },
 fBound = function() {
    
    
 // this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
 return fToBind.apply(this instanceof fBound
 ? this
 : oThis,
 // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
 aArgs.concat(Array.prototype.slice.call(arguments)));
 };
 // 维护原型关系
 if (this.prototype) {
    
    
 // 当执行Function.prototype.bind()时, this为Function.prototype 
 // this.prototype(即Function.prototype.prototype)为undefined
 fNOP.prototype = this.prototype; 
 }
 // 下行的代码使fBound.prototype是fNOP的实例,因此
 // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
 fBound.prototype = new fNOP();
 return fBound;
 };
 var arr=[1,11,5,8,12];
 var max=Math.max.bind(null,arr[0],arr[1],arr[2],arr[3]);
 console.log(max(arr[4])); //12

The difference between apply, call and bind

  • All three can change the this object of the function.
  • The first parameter of the three is the object to be pointed to by this. If there is no such parameter or the parameter is undefined or null, it will point to the global window by default.
  • All three can pass parameters, but apply is an array, and call is a parameter list, and apply and call are passed parameters at once, and bind can be divided into multiple passes.
  • bind returns the function after binding this, which is convenient to call later; apply and call are executed immediately.

Guess you like

Origin blog.csdn.net/uk_51/article/details/115265460