共同点
-
call()
,apply()
,bind()
三个函数都是Function实例对象的属性,也就是说存在于Function.prototype
中。 - 作用都是设置函数体内对象的值,即改变函数运行时的上下文。
- 第一个参数都是运行函数的作用域,即要指定的上下文。
区别
Function.prototype.call()
先来理解一下call()
的作用:
var name = "banana";
var fruits = {
name: "apple"
};
function say() {
console.log("I'm " + this.name);
}
say(); //I'm banana
此时调用say()
的上下文(this)是window对象,所以输出的name为“banana”。如果我想输出name为“apple”那该怎么办?call()
可以解决这个问题:
say.call(fruits); //I'm apple
可以看出call()
能改变函数运行时的this指向。
apply()
、bind()
亦如此。
语法
Function.call(thisObj,[arg1[arg2[argN]]]);
参数
call()
有两个参数,一个(thisObj
)是函数运行的作用域,另一个(arg
)是传给函数的参数,传入的参数必须逐个列举出来。
例子
function sum(num1, num2) {
return num1 + num2;
}
function callSum(num1, num2) {
return sum.call(this, num1, num2);
}
console.log(callSum(10, 10)); //20
Function.prototype.apply()
apply()
的作用与call()
完全相同。
语法
Function.apply(thisObj, [argArray]);
参数
apply()
也有两个参数,一个(thisObj
)是函数运行的作用域,另一个(arg
)是传给函数的参数,与'call()'不同的是传入的参数可以是arguments
对象,也可以是数组。
如果 argArray
不是一个有效的数组或者不是 arguments
对象,那么将导致一个 TypeError。
例子
function sum(num1, num2) {
return num1 + num2;
}
function callSum1(num1, num2) {
return sum.apply(this, arguments);
}
function callSum2(num1, num2) {
return sum.apply(this, [num1, num2]);
}
console.log(callSum1(10, 10)); //20
console.log(callSum2(10, 10)); //20
可以看出,call()
和apply()
作用一样,唯一的区别只是传入参数的形式不同。接下来看一下bind()
函数。
Function.prototype.bind()
语法
Function.bind(thisObj, [arg1[arg2[argN]]])
参数
bind()
传参数方式与call()
相同。但它有一个返回值,MDN上这样介绍:“返回由指定的this值和初始化参数改造的原函数拷贝。”
例子
有时我们需要用到函数外的作用域,这是我们一般会用_this
, $this
等来存储外部函数对象,如下:
var foo = {
num : 1,
eventBind: function() {
var $this = this;
$('.class').on('click',function(event) {
console.log($this.num); //1
});
}
}
这样的做法没有问题,不过我们可以使用bind()
更优雅的解决。
var foo = {
num : 1,
eventBind: function() {
$('.class').on('click',function(event) {
console.log(this.num); //1
}.bind(this));
}
}
call()
、apply()
和bind()
的主要区别是:call()
、apply()
改变上下文之后立即执行,而bind()
只是返回一个函数,不执行。
参考: