bind、apply和call方法之间有什么区别?

13

我在Stack Overflow和网络上搜索,但没有找到关于这三种方法之间区别的合适结果或解释。

据我理解,它们都执行相同的函数/方法,只是在不同的上下文中执行。

var google = {  
    makeBeer : function(arg1,arg2){     
         alert([arg1, arg2]);        
    }    
}

google.makeBeer('water','soda');

这是我对Google对象的常规函数。现在当我在这里使用call和bind方法时,输出如下。

var google = {
    makeBeer: function (arg1, arg2) {
        alert([arg1, arg2]);
    }
}

google.makeBeer('water', 'soda');

function yahoo() {}

var yah = new yahoo();
google.makeBeer.call(yah, 'pepsi', 'coke');

function msn() {

}

var msn = new msn();
google.makeBeer.call(msn, 'sprite', 'limca');

我仍然不明白为什么要这样做,我可以继续调用google.makeBeer三次并使用不同的参数。

有谁能更详细地给我解释一下吗?


1
在您的示例中,这并没有什么区别,因为 google.makeBeer 没有使用 this。当以 google.makeBeer(...); 的形式调用时,函数内部的 this 将引用 google。当以 google.makeBeer.call(yah, ...); 的形式调用时,this 将引用 yahbind 实际上并不执行函数,它创建一个新函数,其中 this 和可选的一些参数绑定到传递的参数上。请参见 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this 和 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind。 - Felix Kling
我认为DOM方法.call().apply()之间的主要区别在于可以传递的参数数量(一个只允许一个,另一个允许更多)。我不确定.bind()的参考是什么,但它通常指事件及其处理程序被“绑定”。 - Jared Farrish
3个回答

14

applycall本质上是相同的,只是一个接受以数组形式传递给函数的参数,而另一个以参数形式传递。

bind根据你使用的框架与callapply执行相同的操作,但不会立即调用函数,而是返回一个新函数,并将您的参数绑定到this,当从新的作用域或上下文中调用函数时,this仍将保持您绑定的内容。绑定还允许您通过applycall来防止构造函数被"篡改",因为它将始终使用绑定的参数作为this,无论其他人发送什么尝试通过callapply覆盖this

以下是一个示例:

function Profile(u) {
    this.user = u;
    this.getUser = function () {
        return this.user;
    };
}

function Profile2(u) {
    this.user = u;
    this.getUser = (function () {
        return this.user;
    });
}

function Profile3(u) {
    this.user = u;
    this.getUser = (function () {
        return this.user;
    });
}

var x = new Profile('guest');
var x2 = new Profile2('guest');
var x3 = new Profile3('guest');

alert(x.getUser.apply({
    user: 'Vinoth'
})); // Vinoth
alert(x2.getUser.call({
    user: 'Babu'
})); // babu
alert(x3.getUser.bind(x3).call({
    user: 'Nandan'
})); // Guest

3

bind函数创建一个拥有相同函数体的新函数,并返回这个新函数。
call函数在不同的上下文中调用相同的函数,参数必须被显式地书写。
apply函数在不同的上下文中调用相同的函数,但是参数必须以数组形式传递。

var f = function(p1, p2) {
    var s = this;
}

var newFunc = f.bind(window, 1, 2);
// here newFunc is a function which when you will call will have this as window and p1 = 1 and p2 = 2

f.call(window, 1, 2);
// by executing this line this = window p1 = 1 and p2 = 2

f.call(document, 2, 3);
// by executing this line this = document p1 = 2 and p2 = 3

f.apply(window, [1, 2]);
// by executing this line this = window p1 = 1 and p2 = 2

.bind 不会执行函数。 - Felix Kling
1
此外,this并不是上下文。它是由调用或绑定设置的本地变量。 - RobG

2

简单来说,apply()和call()之间没有区别,它们之间的唯一区别在于你传递的参数。在apply()中,必须将参数作为数组传递,而在call()方法中,你需要以逗号分隔形式传递参数。

谈到bind方法,这是EcmaScript5中引入的新方法,特别用于解决调用对象方法时的this范围问题。在异步方法调用中,this尤其有用。


1
this不是作用域,它是(本质上)由调用设置的局部变量。 - RobG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接