我已经知道apply和call是类似的函数,它们设置this(函数的上下文)。

区别在于我们发送参数的方式(manual vs array)

问题:

但是什么时候应该使用bind()方法呢?

var obj = {
  x: 81,
  getX: function() {
    return this.x;
  }
};

alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));

jsbin


当前回答

JavaScript中call()、apply()和bind()方法的第一个区别是它们的执行时间! Call()和apply()是相似的立即执行,而bind()创建了一个新函数,我们必须在任何稍后的时间显式调用!

另一个区别是,在传递参数时,call()允许我们用逗号分隔一个一个地传递,apply()允许我们作为参数数组传递,而bind()允许我们两者都做!

我已附上下面的示例代码!

const person = {
    fullName : function (randomMessage) {
        return `Hello, ${this.firstName} ${this.lastName} ${randomMessage}`;
    }
}

const personOne = {
    firstName : "John",
    lastName : "Doe"
}

const personTwo = {
    firstName : "Jack",
    lastName : "Adhikari"
}

let fullNameBind = person.fullName.bind(personOne, "--Binding");
let fullNameCall = person.fullName.call({firstName : "Sarah", lastName: "Holmes"}, "--Calling");
let fullNameApply = person.fullName.apply(personTwo, ["--Applying"]);

console.log(fullNameBind());
console.log(fullNameCall);
console.log(fullNameApply);

其他回答

它们都将其附加到函数(或对象)中,区别在于函数调用(见下文)。

Call将此附加到函数中并立即执行函数:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"

Bind将它附加到函数中,需要像这样单独调用:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
var helloFunc = person.hello.bind({ name: "Jim Smith" });
helloFunc("world");  // output: Jim Smith says hello world"

或者像这样:

...    
var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world");
helloFunc();  // output: Jim Smith says hello world"

Apply类似于call,只是它接受一个类似数组的对象,而不是一次列出一个参数:

function personContainer() {
  var person = {  
     name: "James Smith",
     hello: function() {
       console.log(this.name + " says hello " + arguments[1]);
     }
  }
  person.hello.apply(person, arguments);
}
personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"                                     

在以后调用该函数时使用bind。apply和call都调用函数。

Bind()还允许将附加的参数挂在args数组上。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

function. prototype.call()和function. prototype.apply()都使用给定的这个值调用函数,并返回该函数的返回值。

另一方面,function .prototype.bind()使用给定的这个值创建一个新函数,并返回该函数而不执行它。

让我们取一个这样的函数:

var logProp = function(prop) {
    console.log(this[prop]);
};

现在,让我们选择一个这样的对象:

var Obj = {
    x : 5,
    y : 10
};

我们可以像这样将函数绑定到对象上:

Obj.log = logProp.bind(Obj);

现在,我们可以在代码中的任何地方运行Obj.log:

Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10

真正有趣的是,你不仅为this绑定了一个值,还为它的参数prop绑定了一个值:

Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');

我们现在可以这样做:

Obj.logX(); // Output : 5
Obj.logY(); // Output : 10

这里有一篇很好的文章来说明bind()、apply()和call()之间的区别,总结如下。

bind() allows us to easily set which specific object will be bound to this when a function or method is invoked. // This data variable is a global variable​ var data = [ {name:"Samantha", age:12}, {name:"Alexis", age:14} ] var user = { // local data variable​ data :[ {name:"T. Woods", age:37}, {name:"P. Mickelson", age:43} ], showData:function (event) { var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1​ console.log (this.data[randomNum].name + " " + this.data[randomNum].age); } } // Assign the showData method of the user object to a variable​ var showDataVar = user.showData; showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​ /* This happens because showDataVar () is executed as a global function and use of this inside showDataVar () is bound to the global scope, which is the window object in browsers. */ // Bind the showData method to the user object​ var showDataVar = user.showData.bind (user); // Now the we get the value from the user object because the this keyword is bound to the user object​ showDataVar (); // P. Mickelson 43​ bind() allow us to borrow methods // Here we have a cars object that does not have a method to print its data to the console​ var cars = { data:[ {name:"Honda Accord", age:14}, {name:"Tesla Model S", age:2} ] } // We can borrow the showData () method from the user object we defined in the last example.​ // Here we bind the user.showData method to the cars object we just created.​ cars.showData = user.showData.bind (cars); cars.showData (); // Honda Accord 14​ One problem with this example is that we are adding a new method showData on the cars object and we might not want to do that just to borrow a method because the cars object might already have a property or method name showData. We don’t want to overwrite it accidentally. As we will see in our discussion of Apply and Call below, it is best to borrow a method using either the Apply or Call method. bind() allow us to curry a function Function Currying, also known as partial function application, is the use of a function (that accept one or more arguments) that returns a new function with some of the arguments already set. function greet (gender, age, name) { // if a male, use Mr., else use Ms.​ var salutation = gender === "male" ? "Mr. " : "Ms. "; if (age > 25) { return "Hello, " + salutation + name + "."; }else { return "Hey, " + name + "."; } } We can use bind() to curry this greet function // So we are passing null because we are not using the "this" keyword in our greet function. var greetAnAdultMale = greet.bind (null, "male", 45); greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove." var greetAYoungster = greet.bind (null, "", 16); greetAYoungster ("Alex"); // "Hey, Alex."​ greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo." apply() or call() to set this value The apply, call, and bind methods are all used to set the this value when invoking a method, and they do it in slightly different ways to allow use direct control and versatility in our JavaScript code. The apply and call methods are almost identical when setting the this value except that you pass the function parameters to apply () as an array, while you have to list the parameters individually to pass them to the call () method. Here is one example to use call or apply to set this in the callback function. // Define an object with some properties and a method​ // We will later pass the method as a callback function to another function​ var clientData = { id: 094545, fullName: "Not Set", // setUserName is a method on the clientData object​ setUserName: function (firstName, lastName) { // this refers to the fullName property in this object​ this.fullName = firstName + " " + lastName; } }; function getUserInput (firstName, lastName, callback, callbackObj) { // The use of the Apply method below will set the "this" value to callbackObj​ callback.apply (callbackObj, [firstName, lastName]); } // The clientData object will be used by the Apply method to set the "this" value​ getUserInput ("Barack", "Obama", clientData.setUserName, clientData); // the fullName property on the clientData was correctly set​ console.log (clientData.fullName); // Barack Obama Borrow functions with apply or call Borrow Array methods Let’s create an array-like object and borrow some array methods to operate on the our array-like object. // An array-like object: note the non-negative integers used as keys​ var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 }; // Make a quick copy and save the results in a real array: // First parameter sets the "this" value​ var newArray = Array.prototype.slice.call (anArrayLikeObj, 0); console.log (newArray); // ["Martin", 78, 67, Array[3]]​ // Search for "Martin" in the array-like object​ console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true​ Another common case is that convert arguments to array as following // We do not define the function with any parameters, yet we can get all the arguments passed to it​ function doSomething () { var args = Array.prototype.slice.call (arguments); console.log (args); } doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"] Borrow other methods var gameController = { scores :[20, 34, 55, 46, 77], avgScore:null, players :[ {name:"Tommy", playerID:987, age:23}, {name:"Pau", playerID:87, age:33} ] } var appController = { scores :[900, 845, 809, 950], avgScore:null, avg :function () { var sumOfScores = this.scores.reduce (function (prev, cur, index, array) { return prev + cur; }); this.avgScore = sumOfScores / this.scores.length; } } // Note that we are using the apply () method, so the 2nd argument has to be an array​ appController.avg.apply (gameController); console.log (gameController.avgScore); // 46.4​ // appController.avgScore is still null; it was not updated, only gameController.avgScore was updated​ console.log (appController.avgScore); // null​ Use apply() to execute variable-arity function

的数学。Max是变量函数的一个例子,

// We can pass any number of arguments to the Math.max () method​
console.log (Math.max (23, 11, 34, 56)); // 56

但是如果我们有一个数字数组要传递给Math.max呢?我们不能这样做:

var allNumbers = [23, 11, 34, 56];
// We cannot pass an array of numbers to the the Math.max method like this​
console.log (Math.max (allNumbers)); // NaN

这就是apply()方法帮助我们执行可变函数的地方。与上述方法不同,我们必须使用apply()传递数字数组,如下所示:

var allNumbers = [23, 11, 34, 56];
// Using the apply () method, we can pass the array of numbers:
console.log (Math.max.apply (null, allNumbers)); // 56

call():——这里我们单独传递函数参数,而不是数组格式

var obj = {name: "Raushan"};

var greeting = function(a,b,c) {
    return "Welcome "+ this.name + " to "+ a + " " + b + " in " + c;
};

console.log(greeting.call(obj, "USA", "INDIA", "ASIA"));

apply():——这里我们以数组格式传递函数参数

var obj = {name: "Raushan"};

var cal = function(a,b,c) {
    return this.name +" you got " + a+b+c;
};

var arr =[1,2,3];  // array format for function arguments
console.log(cal.apply(obj, arr)); 

bind (): -

       var obj = {name: "Raushan"};

       var cal = function(a,b,c) {
            return this.name +" you got " + a+b+c;
       };

       var calc = cal.bind(obj);
       console.log(calc(2,3,4));