Bind this method

This article will show you how to bind this by comparing call, apply, and bind.

call

Function.prototype.call()

A single parameter

The call method of a function instance changes the direction of this within the function.

var x="in window";
var obj={
    x:"in obj",
    fun:function(){
    console.log(this.x);
}
};

obj.fun(); //"in obj"
obj.fun.call(window);//"in window"
Copy the code

The above code shows that the call function takes the specified argument as the execution environment (pointing to) for this within the function.

Call should take an object as a parameter, and if the parameter is a primitive value, the primitive value is automatically converted to the corresponding wrapper object, which is passed to the Call method.

var f = function () {
  return this;
};

f.call(5)
// Number {[[PrimitiveValue]]: 5}
Copy the code

In the code above, call takes 5, is not an object, and is automatically converted to a wrapper object (an instance of Number), bound to this inside f.

Multiple parameters

The call method can take multiple arguments

func.call(thisValue, arg1, arg2, ...)
Copy the code

The first argument to the call method is the object to which this refers, followed by arguments needed to execute the function.

function add(a, b) {
  return a + b;
}

add.call(this, 1, 2) // 3
Copy the code

The above code indicates that the call method specifies the function add as the execution environment for this, passing in the argument 1,2 and returning the result 3.

application

One application of the call method is the native method of calling an object

The following code is usedcallAn example of solving the function name problem.

var obj = {}; Obj. hasOwnProperty = function () {return true; obj.hasOwnProperty = function () {return true; }; obj.hasOwnProperty('toString') // true Object.prototype.hasOwnProperty.call(obj, 'toString') // falseCopy the code

Initially, the Object obj’s hasOwnProperty method inherits from Object, which can cause unnecessary errors when accidentally overridden. So you can use call to place the original definition of the hasOwnProperty method on an OBJ object so that it doesn’t affect the result whether there is a method with the same name on obJ.

apply

Function.prototype.apply() The apply method is similar to the call method except that it receives the parameters of the Function as an array

func.apply(thisValue, [arg1, arg2, ...] )Copy the code

The first argument to the apply method is also the object to which this points. If set to null or undefined, this specifies the global object. The second argument is an array whose members are, in turn, passed as arguments to the original function.

application

Find the largest element in the array

The apply and math.max methods are combined to return the largest element in an array

Var arr =,43,123,42 [12421]; Math.max.apply(null,arr); / / 421Copy the code
(2) Change an empty element of the array to undefined

The apply method uses the Array constructor to change an empty element of the Array to undefined.

var arr=[12,,43]; Array.apply(null,arr); [12,undefined,43];Copy the code

The difference between an empty element and undefined is that the forEach method of an array skips empty elements instead of undefined.

var arr=[12,,13]; arr.forEach(item=>console.log(item)); //12 13 Array.apply(null,arr).forEach(item=>console.log(item)) //12 undefined 13Copy the code
(3) Convert an array-like object

Additionally, an array-like object (such as the Arguments object) can be turned into a real array using the slice method of array objects.

Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
Copy the code

The apply method takes objects, but returns an array as a result, which serves the purpose of converting objects to arrays. As you can see from the code above, this method works only if the object being processed has a length attribute and the corresponding numeric key.

(4) The object bound to the callback function
var o = new Object(); o.f = function () { console.log(this === o); } var f = function (){ o.f.apply(o); / / or O.F.C all (o); }; $('#button'). On ('click', f);Copy the code

In the code above, there is a button on the page that, when clicked, will display True on the console. Using the apply() method (or call() method) not only binds to the object on which the function is executed, but also executes the function immediately, so you have to write the binding statement inside a function body. A more concise way to write this is to use the bind() method described below.

bind

The function.prototype.bind () bind() method is used to bind this inside a Function to an object and return a new Function.

var d=new Date(); d.getTime(); 1606483094579 var print=d.getTime; print(); //Uncaught TypeError: this is not a Date object.Copy the code

You can use bind to bind this from the d.getime method to an object

var d=new Date(); d.getTime(); 1606483094579 var print=d.getTime.bind(d); print(); / / 1606483094579Copy the code

In the code above, the bind() method binds this inside the getTime() method to the D object, where it is safe to assign the method to other variables.

Use methods of other objects

var obj1={ name:"obj1", show:function(){ console.log(this.name); }}; var obj2={ name:"obj2" }; obj1.show(); //obj1 var showobj=obj1.show.bind(obj2); show(); //obj2Copy the code

Pay attention to

(1) Return a new function each time

The bind() method generates a new function each time it is run, so you cannot write listening events in the following form.

element.addEventListener('click', o.m.bind(o));
Copy the code

The above code shows that the click event binds to an anonymous function generated by the bind() method, which causes the unbinding (removeEventListener) to be impossible.

It can be written in the following form by reference

var listener = o.m.bind(o);
element.addEventListener('click', listener);
//  ...
element.removeEventListener('click', listener);
Copy the code

You can solve this problem by giving the function a name.

(2)call()methods

Bind () allows you to override the use of some JavaScript native methods.

Var arr = [1, 2, 3, 4, 5]; Arr. Slice (0, 3); / / [1, 2, 3]; / / is equivalent to an Array. The prototype. Slice. Call (arr, 0, 3);Copy the code

By rewriting

var slice=Function.prototype.call.bind(Array.prototype.slice); Slice (arr. 0, 3); / / [1, 2, 3]Copy the code

Code above is that the meaning of the Array. The prototype. Slice into the Function. The prototype. The call method of objects, called becomes Array. The prototype. Slice. Call on the pop and push to rewrite

Var arr = [1, 2, 3, 4]; var pop=Function.prototype.call.bind(Array.prototype.pop); var push=Function.prototype.call.bind(Array.prototype.push); pop(arr); / / [1, 2, 3] push (arr, 9,8,7); / /,2,3,9,8,7 [1]Copy the code
Rewrite bind to use the form

If you go a step further and bind the function.prototype. call method to the function.prototype. bind object, that means that the call form of bind can also be overridden.

function f() {
  console.log(this.v);
}

var o = { v: 123 };
var bind = Function.prototype.call.bind(Function.prototype.bind);
bind(f, o)() // 123
Copy the code

Bind (function.prototype. call); bind (function.prototype. call); bind (function.prototype. call);

In the previous This keyword explanation 1

Finally, I hope we can make progress together!