Call, apply, bind, call, bind, call, bind, call, bind, call, bind
1. Basic introduction
Grammar:
function.call(thisArg, arg1,arg2,arg3,...);
function.apply(thisArg, [arg1, arg2, arg3,...]);
function.bind(thisArg, arg1,arg2,arg3,...);Copy the code
Call /apply/bind must be a function; call/apply/bind must be a function;
Since call/apply/bind can redirect functions, let’s have math.max call each of these methods in turn;
// Before calling:
Math.max(2.4.10.3.5); / / 10Copy the code
After the call:
ThisArg, [arg1,arg2,arg3]
Math.max.apply(null[2.4.10.3.5]); / / 10
// Call (thisArg, arg1,arg2,arg3...
Math.max.call(null.2.4.10.3.5); / / 10
/ / use the bind
//
const Max = Math.max.bind(null.2.4.10.3.5); // Bind will not be executed immediately
Max(); / / 10
//
Math.max.bind(null.2.4.10.3.5) ();/ / 10Copy the code
Note: in the browser, null refers to the global window, or undefined, can be verified by yourself;
2, Call, apply, bind
The difference between Call and apply is that the call method accepts a list of parameters, while apply accepts an array of parameters.
What is the difference between a bind and a call or a apply?
Call and apply are executed immediately after a function is called, while bind returns a new function that needs to be called again. React constructor now uses bind to change this pointer instead of call and apply.
3, write Polyfill for call, apply, bind by hand
So what is Polyfill? Polyfill is front-end slang, which exactly means code to implement a native API that the browser doesn’t support.
The call of the Polyfill
Function.prototype.myCall = function(thisArg, ... args){
if (typeof thisArg === null || typeof thisArg === 'undefined') {
thisArg = window;
}
let mySymbol = Symbol(a); thisArg[mySymbol] =this;
letfunc = thisArg[mySymbol](... args);delete thisArg[mySymbol];
return func;
}Copy the code
The apply of Polyfill
Function.prototype.myApply = function(thisArg, args){
if (typeof thisArg === null || typeof thisArg === 'undefined') {
thisArg = window;
}
let mySymbol = Symbol()
thisArg[mySymbol] = this;
letfunc = thisArg[mySymbol](... args);return func;
}Copy the code
Bind the polyfill
// Method 1:
Function.prototype.myBind = function (thisArg,... list) {
let self = this; // Target function
let Bind = function(. args){
// If this function is used as a constructor, then the target function this should execute the instance object;
// If this function is not used as a constructor, this in the target function also refers to thisArg;
let thisArgSelf = this instanceof Bind ? this : thisArg;
self.apply(thisArg, [...list, ...args])
};
// Prototype inheritance
// object.create Creates an Object that is modeled after an Object
Bind.prototype = Object.create(self.prototype);
Bind.prototype.constructor = self;
// Return the new function
return Bind;
}
/ / method 2: source bind MDN (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
if (!Function.prototype.bind) (function(){
var slice = Array.prototype.slice;
Function.prototype.bind = function(){
var self = this, thatArg = arguments[0];
var args = slice.call(arguments.1);
if (typeofself ! = ='function') {
throw new TypeError('this is not callable')}return function () {
var funcArgs = args.concat(slice.call(arguments));
returnself.apply(thatArg, funcArgs); }}}) ()Copy the code
Example 4,
Call examples
1, sample
function sum(a,b){
return a+b;
};
function minus(a, b){
return a - b;
};
sum.call(minus, 5.3); / / 8
Copy the code
(Personal conclusion: if sum is a and B under minus, then sum is a = 5 and b =3, but the execution method of the called function is not changed, that is, to change this is nothing but to change the scope);
2. Convert the class array to an array
(function(){
let arr = Array.prototype.slice.call(arguments.0);
// Array.prototype.slice.call(arguments, start, end);
console.log('arr', arr); / /,22,33 [11]}) (11.22.33)Copy the code
Feed (class array to array) finish:
// 1, Array.prototype.slice.call(arrayLike); // 2, Array.from(arrayLike); // 3, [...arrayLike] note: the third method of extending operations can only be used for objects that define an Iterator interface;Copy the code
Apply
1. Get the maximum value in the array
/* Find the largest/smallest number in the array */
var nums = [51.62.21.32.72];
/* Basic equivalent to math.max (nums[0],...) Or Math. Max (51, 62) that... * /
var max = Math.max.apply(null, nums);
var min = Math.min.apply(null, nums);Copy the code
Add an array to another array using apply:
var arr = [3.4.5];
var otherArr = ['a'.'b'.'c'];
arr.push.apply(arr, otherArr);
console.log(arr); / / [three, four, five, 'a', 'b', 'c']Copy the code
Bind
1. Create a binding function
this.name = '千钧'; // In the browser, this refers to the global window object
var obj = {
name: 'Lucy'.getName: function(){
console.log(this);
return this.name; }}; obj.getName();// 'Lucy'; // this points to obj
var otherName = obj.getName; // This points to window because otherName = window.obj.getName;
otherName(); // '1000 jun'
var bindName = otherName.bind(obj);
bindName(); // 'Lucy'Copy the code
Note: If getName changes from a normal function to an arrow function, the scope changes; The result is as follows:
this.name = '千钧'; // In the browser, this refers to the global window object
var obj = {
name: 'Lucy'.getName: (a)= > {
console.log(this); // this is the window global environment where obj is located
return this.name; }}; obj.getName();// 'qian jun '; var otherName = obj.getName; / / obj for Windows. Obj
otherName(); // '1000 jun'
var bindName = otherName.bind(obj); / / obj for Windows. Obj
bindName(); // '1000 jun'Copy the code
2. Give the function a default initial argument
var addArguments = function(arg1, arg2){
return arg1 + arg2;
};
// Create a function with a default first argument
var addInit = addArguments.bind(null.20);
addInit(30); / / 50
addInit(40.50); // 60 = 20 + 40, the second argument is ignoredCopy the code
summary
Call, apply, and bind all change this. Call and apply are executed immediately, while bind creates a new function that needs to be called. 2. Call, apply, and bind are often used in source code. If you are not familiar with these three methods, it will be difficult to interpret some source libraries. This is also a common interview question.
Ps: There are still some shortcomings in this paper, and we will continue to optimize and update it in the future.