我已经知道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


当前回答

这里有一篇很好的文章来说明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

其他回答

当您希望稍后在特定上下文中调用该函数(在事件中很有用)时,请使用.bind()。当您希望立即调用函数并修改上下文时,请使用.call()或.apply()。

Call/apply立即调用该函数,而bind返回的函数在稍后执行时将具有用于调用原始函数的正确上下文设置。这样你就可以在异步回调和事件中维护上下文。

我经常这样做:

function MyObject(element) {
    this.elm = element;

    element.addEventListener('click', this.onClick.bind(this), false);
};

MyObject.prototype.onClick = function(e) {
     var t=this;  //do something with [t]...
    //without bind the context of this function wouldn't be a MyObject
    //instance as you would normally expect.
};

我在Node.js中广泛使用它,用于我想要传递成员方法的异步回调,但仍然希望上下文是启动异步操作的实例。

bind的简单实现如下所示:

Function.prototype.bind = function(ctx) {
    var fn = this;
    return function() {
        fn.apply(ctx, arguments);
    };
};

还有更多关于它的内容(比如传递其他参数),但您可以阅读更多关于它的内容,并查看MDN上的实际实现。

这里有一篇很好的文章来说明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

调用apply和bind。以及它们的不同之处。

让我们学习如何使用日常术语。

你有三辆汽车,你的摩托车,你的汽车和你的喷气式飞机,它们以相同的机制(方法)开始。 我们使用push_button_engineStart方法创建了一个对象汽车。

var your_scooter, your_car, your_jet;
var automobile = {
        push_button_engineStart: function (runtime){
        console.log(this.name + "'s" + ' engine_started, buckle up for the ride for ' + runtime + " minutes");
    }
}

让我们理解什么时候使用call和apply。让我们假设你是一名工程师,你有你的摩托车,你的汽车和你的喷气式飞机,这些都没有push_button_engine_start,你希望使用第三方push_button_engineStart。

如果运行以下代码行,它们将给出一个错误。为什么?

//your_scooter.push_button_engineStart();
//your_car.push_button_engineStart();
//your_jet.push_button_engineStart();


automobile.push_button_engineStart.apply(your_scooter,[20]);
automobile.push_button_engineStart.call(your_jet,10);
automobile.push_button_engineStart.call(your_car,40);

上面的例子成功地给了your_scooter, your_car, your_jet一个automobile对象的特征。

让我们再深入一点 在这里,我们将拆分上面的代码行。 汽车。push_button_engineStart帮助我们获取正在使用的方法。

此外,我们使用点表示法使用apply或call。 automobile.push_button_engineStart.apply ()

现在应用和调用accept两个参数。

上下文 参数

这里我们在最后一行代码中设置了context。

automobile.push_button_engineStart.apply (your_scooter [20])

call和apply的区别在于apply接受数组形式的形参,而call只能接受以逗号分隔的参数列表。

什么是JS绑定函数?

绑定函数基本上就是绑定某个东西的上下文,然后将其存储到一个变量中,以便在稍后阶段执行。

让我们把前面的例子做得更好。之前我们使用了一个属于automobile对象的方法,并使用它来装备你的car、你的jet和你的scooter。现在让我们想象一下,我们想要分别给出一个单独的push_button_engineStart,在我们希望的执行的任何后续阶段分别启动我们的汽车。

var scooty_engineStart = automobile.push_button_engineStart.bind(your_scooter);
var car_engineStart = automobile.push_button_engineStart.bind(your_car);
var jet_engineStart = automobile.push_button_engineStart.bind(your_jet);


setTimeout(scooty_engineStart,5000,30);
setTimeout(car_engineStart,10000,40);
setTimeout(jet_engineStart,15000,5);

还不满意?

让我们像泪滴一样说清楚。是时候做实验了。我们将返回到调用和应用函数应用程序,并尝试将函数的值存储为引用。

下面的实验失败了,因为call和apply是立即调用的,因此,我们从来没有达到在变量中存储引用的阶段,这是bind函数的亮点

var test_function = automobile.push_button_engineStart.apply(your_scooter);

它允许设置该函数的值,而不依赖于函数的调用方式。这在处理回调时非常有用:

  function sayHello(){
    alert(this.message);
  }

  var obj = {
     message : "hello"
  };
  setTimeout(sayHello.bind(obj), 1000);

要用call实现相同的结果,应该是这样的:

  function sayHello(){
    alert(this.message);
  }

  var obj = {
     message : "hello"
  };
  setTimeout(function(){sayHello.call(obj)}, 1000);

Call, Apply和Bind之间的基本区别是:

如果您希望执行上下文出现在图的后面,则将使用Bind。

Ex:

var car = { 
  registrationNumber: "007",
  brand: "Mercedes",

  displayDetails: function(ownerName){
    console.log(ownerName + ' this is your car ' + '' + this.registrationNumber + " " + this.brand);
  }
}
car.displayDetails('Nishant'); // **Nishant this is your car 007 Mercedes**

假设我想在其他变量上使用这个方法

var car1 = car.displayDetails('Nishant');
car1(); // undefined

在你应该使用的其他变量中使用car的引用

var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes

让我们讨论bind函数的更广泛使用

var func = function() {
 console.log(this)
}.bind(1);

func();
// Number: 1

为什么?因为现在func与编号1绑定,如果我们不使用bind,它将指向全局对象。

var func = function() {
 console.log(this)
}.bind({});

func();
// Object

当您希望同时执行语句时,将使用Call、Apply。

var Name = { 
    work: "SSE",
    age: "25"
}

function displayDetails(ownerName) {
    console.log(ownerName + ", this is your name: " + 'age' + this.age + " " + 'work' + this.work);
}
displayDetails.call(Name, 'Nishant')
// Nishant, this is your name: age25 workSSE

// In apply we pass an array of arguments
displayDetails.apply(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE