Call, bind, apply

role

Change the execution context of the function, that is, the reference to this when the function is run.

The essence

Rebind the parameters to the function.

The difference between

Call and apply accept different parameters.

  • The first argument to call is a reference to this, starting with the second argument is the list of arguments received

  • The first argument to apply is the value to bind to this, and the second argument is an array of arguments. When the first parameter is null, undefined, the default point is window.

  • It’s all done immediately

Bind is similar to call. The first argument is the reference to this, and the second argument is the list of arguments received. The difference is that the bind method returns a function and uses a list of arguments that BIND receives.

Simulate the implementation of call

  • Decide whether this current is a Function, prevent the Function prototype. MyCall () call directly
  • Context is optional. If not, the default context is Window
  • Create a Symbol property for the context and assign the current function to the property
  • Process parameters, passing in the remaining parameters after the first parameter
  • The Symbol property is deleted when the function is called
Function.prototype.myCall = function(content = window. args) {
   if(this= = =Function.prototype) return undefined; / / whether the current this Function, prevent the Function. The prototype. MyCall () call directly
   if(typeof this! = ='function') throw new TypeError('The this must be a Function'); // must be a function
   const fn = Symbol(a); content[fn] =this;
   constresult = content[fn](... args);delete context[fn]
   return result;
}
Copy the code

Simulation implementation of Apply

Function.prototype.myApply = function(content = window, args) { if(this === Function.prototype) return undefined; / / whether the current this Function, prevent the Function. The prototype. MyCall () called directly if (typeof this! == 'function') throw new TypeError('The `this` must be a `Function`'); // must be a function const fn = Symbol(); content[fn] = this; const result = Array.isArray(args) ? content[fn](... args) : content[fn](); Delete content[fn] return result; }Copy the code

Mock implementation of BIND

  • Process parameters and return a closure
  • The returned new function can also use the new operator, so inside the new function you need to determine whether the new operator is used, whether it is a constructor call, and if so, use new to call the current function
  • If not, use apply, passing in the context and the processed parameters
Function.prototype.myBind = function(content = window, ... args) { if(this === Function.prototype) return undefined; / / whether the current this Function, prevent the Function. The prototype. MyCall () called directly if (typeof this! == 'function') throw new TypeError('The `this` must be a `Function`'); // must be a function const fn = this; return function F(... OtherArgs) {if(this instanceof F) return new fn(... args, ... otherArgs); Return fn. Apply (content, [...args,...otherArgs])}} function new(constructor) {var obj = {}; // create an empty object obj obj.__proto__ = constructor. Prototype; // Assign the constructor's prototype object to obj's prototype contructor.apply(obj); Return obj (); return obj (); // Step 4: Return this object} Some people use the following stupid method, but you can understand why. Function.prototype.myBind2 = function(content = window, ... args) { const fn = this; Const F = function(...) const F = function(...) const F = function(... otherArgs) { return fn.apply(this instanceof T ? Const T = function(){} t.protoType = fn. Prototype; const T = function(){} t.prototype; F.prototype = new T(); // Finally new here. // f.protoType = new T() puts f.protoType's __poro__ to t.prototype, then t.protoType = that.prototype, Prototype return F; fn. Prototype return F; }Copy the code