Call apply and bind

In JavaScript, call, apply, and bind are three built-in methods of Function objects. This article will use several scenarios to understand the three methods in detail.

call()

The call() method calls a function or method that takes a specified this value and several specified parameter values.

When a function is called, a different this object can be assigned. This refers to the current object, the first argument to the call method.

By the method of the call, you can borrow another Object to an Object on the methods, such as the Object. The prototype. ToString. Call ([]), is an Array Object to borrow the method on the Object.

Fun. call(thisArg[, arg1[, arg2[,…]])

thisArg

The this value specified when fun is run. Here are a few things to watch out for

(1) Do not pass, or null, undefined, this refers to the window object. (2) Pass the function name of another function. This in a function refers to a reference to that function, not necessarily the actual value of this when the function is executed. String, Number, Boolean (4) pass an object to which this refers

arg1, arg2, …

Specifies the argument list.

example

Primary application Examples

function a(){
    // Outputs this object in function A
    console.log(this); 
}
// define function b
function b(){} 

var obj = {name:'This is a dick.'}; // Define object obj
a.call(); //window
a.call(null); //window
a.call(undefined);//window
a.call(1); //Number
a.call(' '); //String
a.call(true); //Boolean
a.call(b);// function b(){}
a.call(obj); //ObjectCopy the code

Use the call method to call an anonymous function and specify this for the context

In the following example, when the greet method is called, its this value is bound to the I object.

function greet() {
  var reply = [this.person, 'It's a lightweight.'.this.role].join(' ');
  console.log(reply);
}

var i = {
  person: 'JSLite.io', role: 'the Javascript library. '
};

greet.call(i); 
// Jslite. IO is a lightweight Javascript library.Copy the code

Call anonymous functions using the call method

In the for loop in the following example, we create an anonymous function and execute that anonymous function with each array element as the specified this value by calling the call method of that function. The main purpose of this anonymous function is to add a print method to each array element object. This print method prints out the correct index number of each element in the array. Of course, you don’t have to pass the array element as the this value to the anonymous function (normal arguments will do), just to demonstrate the use of call.

var animals = [
  {species: 'Lion', name: 'King'},
  {species: 'Whale', name: 'Fail'}];for (var i = 0; i < animals.length; i++) {
  (function (i) { 
    this.print = function () { 
      console.log(The '#' + i  + ' ' + this.species + ':' + this.name); 
    } 
    this.print();
  }).call(animals[i], i);
}
//#0 Lion: King
//#1 Whale: FailCopy the code

Use the call method to call a function and pass parameters

var a = {
    name:'JSLite.io'.// Define attributes of a
    say:function(){ // Define a's method
        console.log("Hi,I'm function a!"); }};function b(name){
    console.log("Post params: "+ name);
    console.log("I'm "+ this.name);
    this.say();
}

b.call(a,'test');
//Post params: test
//I'm JSLite.io
//I'm function a!Copy the code

apply()

The syntax is almost identical to that of the call() method, except that the second argument to apply must be an array (or array-like object) containing multiple arguments. This feature of Apply is important,

When calling an existing function, you can specify a this object for it. This refers to the current object, the object on which the function is being called. With Apply, you can write the method once and then inherit it from another object instead of repeating the method in a new object.

Syntax: fun.apply(thisArg[, argsArray])

Note: Note that Chrome 14 and Internet Explorer 9 still do not accept array-like objects. If an array-like object is passed in, they throw an exception.

parameter

thisArg

Same as the thisArg parameter for call above.

argsArray

An array or array-like object whose array elements are passed as separate arguments to fun. If the value of this parameter is null or undefined, no arguments need to be passed in. Array-like objects can be used starting with ECMAScript 5.

example

function jsy(x,y,z){
    console.log(x,y,z);
}

jsy.apply(null[1.2.3]); 
/ / 1 2 3Copy the code

An example of using apply to link the constructor

You can use Apply to assign an object link constructor, similar to Java. In the following example we will create a global Function called Construct, which allows you to use an array-like object instead of a list of parameters in the constructor.

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, 
  fNewConstr = function() { 
    fConstructor.apply(this, aArgs); 
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};
function MyConstructor () {
    for (var nProp = 0; nProp < arguments.length; nProp++) {
        console.log(arguments.this)
        this["property" + nProp] = arguments[nProp]; }}var myArray = [4."Hello world!".false];
var myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);                // logs "Hello world!"
console.log(myInstance instanceof MyConstructor); // logs "true"
console.log(myInstance.constructor);              // logs "MyConstructor"Copy the code

Use Apply and the built-in functions

Clever use of apply allows you to use built-in functions for tasks that would otherwise need to be written to iterate over a set of variables. In the following examples we will use math.max/math.min to find the maximum/minimum value in an array.

// An array object containing the maximum and minimum numeric values
var numbers = [5.6.2.3.7];

/* Apply */ with math.min/math.max
var max = Math.max.apply(null, numbers);
Math.max(5, 6,..) Or Math. Max (Numbers [0],...). To find the maximum
var min = Math.min.apply(null, numbers);

// Usually we do this to find the maximum or minimum value of a number
// Compared with the chestnuts on the top, does the bottom look less comfortable than the top?
max = -Infinity, min = +Infinity;
for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max)
    max = numbers[i];
  if (numbers[i] < min) 
    min = numbers[i];
}Copy the code

The parameter array is sliced and passed in loop

function minOfArray(arr) {
  var min = Infinity;
  var QUANTUM = 32768;

  for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
    var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
    console.log(submin, min)
    min = Math.min(submin, min);
  }

  return min;
}

var min = minOfArray([5.6.2.3.7]);Copy the code

bind

Bind () creates a new function (called the bind function)

  • Bind is a new method in ES5
  • Passing parameters is similar to call or apply
  • The corresponding function is not executed; call or Apply automatically executes the corresponding function
  • Returns a reference to a function

Fun. bind(thisArg[, arg1[, arg2[,…]]])

IO p1 p2. This in EventClick has been changed to obj by bind. If you change eventClick. bind(obj,’p1′,’p2′) to eventClick. call(obj,’p1′,’p2′), the page will output jslite. IO p1 p2

var obj = {name:'JSLite.io'};
/** * Bind this to obj and pass p1,p2 */
document.addEventListener('click',EventClick.bind(obj,'p1'.'p2'),false);
// Trigger and execute when a web page is clicked
function EventClick(a,b){
    console.log(
            this.name, //JSLite.io
            a, //p1
            b  //p2)}// JSLite.io p1 p2Copy the code

Compatible with

if (!Function.prototype.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.// This refers to the target function
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP
                 ? this // This is the new obj
                 : oThis || this.// If the oThis passed is invalid, the caller of fBound is this

               // The arguments passed through bind are merged with those passed on the call and passed as final arguments
               aArgs.concat(Array.prototype.slice.call(arguments)));
        };
    fNOP.prototype = this.prototype;
    // Copy the prototype object of the target function into the new function, since the target function may be used as a constructor
    fBound.prototype = new fNOP();
    // Returns a reference to fBond, called externally on demand
    return fBound;
  };
}Copy the code

Compatibility examples are from: developer.mozilla.org/zh-CN/docs/…

Application scenario: Inheritance

function Animal(name,weight){
   this.name = name;
   this.weight = weight;
}
function Cat(){
    // Pass this as thisArgs in call
    // This in Animal refers to this in Cat
    // Animal this refers to cat
    // Defining the name and weight attributes in Animal is equivalent to defining these attributes in cat
    // The cat object has the property defined in Animal, thus achieving inheritance purposes
    Animal.call(this.'cat'.'50');
    //Animal.apply(this,['cat','50']);
    this.say = function(){
       console.log("I am " + this.name+",my weight is " + this.weight); }}// When cat is generated using the new operator, this in cat refers to the cat object
var cat = new Cat();
cat.say();
// Output => I am cat,my weight is 50Copy the code

Prototype extension

Extend and customize methods on the prototype functions without contaminating the native functions. For example, we extend a forEach on Array

function test(){
    // Check whether arguments is an instance of Array
    console.log(
        arguments instanceof Array.//false
        Array.isArray(arguments)  //false
    );
    // Check whether arguments has a forEach method
    console.log(arguments.forEach); 
    // undefined
    // Apply the array forEach to arguments
    Array.prototype.forEach.call(arguments.function(item){
        console.log(item); // 1, 2, 3, 4
    });
}
test(1.2.3.4);Copy the code