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


当前回答

TL; diana:

简单地说,bind创建函数,调用和apply执行函数,而apply期望数组中的参数

完整的解释

假设有一个乘法函数

function multiplication(a,b){
console.log(a*b);
}

让我们使用bind创建一些标准函数

var multiby2 = multiplication.bind(this,2);

现在multiby2(b)等于乘法(2,b);

multiby2(3); //6
multiby2(4); //8

如果我在bind中传递两个参数会怎样

var getSixAlways = multiplication.bind(this,3,2);

现在getSixAlways()等于乘法(3,2);

getSixAlways();//6

即使传递参数也返回6; getSixAlways (12);/ / 6

var magicMultiplication = multiplication.bind(this);

这将创建一个新的乘法函数并将其分配给magic乘法。

哦,不,我们将乘法功能隐藏到magic乘法中。

调用 magic乘法返回一个空函数b()

在执行过程中,它运行良好 magicMultiplication (6 5);/ / 30

打电话申请怎么样?

magicMultiplication.call(这3 2);/ / 6

magicMultiplication.apply(这一点,[5,2]);/ / 10

其他回答

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

当您希望稍后在特定上下文中调用该函数(在事件中很有用)时,请使用.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上的实际实现。

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"                                     

调用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);