apply、call 、bind 对 JavaScript 新手来说可能是在其他语言中没有遇到过的新概念,要理解这三个方法的作用和区别,还需要先理解在不同情况下 this 的值,可以参考这两篇文章:
Function.prototype.bind()
fun.bind(thisArg[, arg1[, arg2[, ...]]])
返回一个新函数,新函数与被调函数(绑定函数的目标函数)具有相同的函数体,并且指定函数内部的 this 为传入的第一个参数。绑定函数被调用时,bind() 也接受预设的参数提供给原函数。
thisArg
当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new操作符调用绑定函数时,该参数无效。
arg1, arg2, ...
当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
bind() 最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的 this 值。
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象
// 新手可能会被全局的x变量和module里的属性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
参考:Function.prototype.bind() - JavaScript | MDN
Function.prototype.apply()
fun.apply(thisArg[, argsArray])
thisArg
在 fun 函数运行时指定的 this值。
需要注意的是,指定的 this值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,如果指定为 null 或 undefined ,则会自动指向全局对象(浏览器中就是window对象),如果指定为原始值(数字,字符串,布尔值)的 this,则会指向该原始值的自动包装对象。
argsArray
一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。从ECMAScript 5 开始可以使用类数组对象。
例如,使类数组对象 arguments 调用数组的 join 方法:
function joinStr(){
return Array.prototype.join.apply(arguments, ['-']);
}
joinStr('a', 'b', 'cc') // a-b-cc
参考:Function.prototype.apply() - JavaScript | MDN
Function.prototype.call()
apply() 与 call()非常相似,只有一个区别,就是call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。
fun.call(thisArg[, arg1[, arg2[, ...]]])
thisArg
在fun函数运行时指定的this值。特性与apply的第一个参数相同。
arg1, arg2, ...
指定的参数列表。
上面apply的例子如果使用call实现,只需改动参数格式即可:
function joinStr(){
return Array.prototype.join.call(arguments, '-');
}
joinStr('a', 'b', 'cc') // a-b-cc