JavaScript函数存在「 定义时上下文
」和「 运行时上下文
」以及「 上下文是可以改变的
」这样的概念
call() 和 apply()都是为了改变某个函数 运行时的上下文
(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向
call()方法接受的是一个 参数列表
,而apply()方法接受的是一个包含多个参数的 数组
(或类数组对象)
fun.apply(thisArg[, argsArray]) 参数: thisArg 在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。 argsArray 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。 fun.call(thisArg[, arg1[, arg2[, ...]]]) 参数: thisArg 在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。 arg1, arg2, ... 指定的参数列表
function a(xx, yy) { alert(xx, yy); alert(this); alert(arguments); } a.apply(null, [5, 55]); a.call(null, 5, 55);
bind()方法会 创建一个新函数
,当这个新函数被调用时,它的this值是传递给bind()的第一个参数, 它的参数是bind()的其他参数和其原本的参数
fun.bind(thisArg[, arg1[, arg2[, ...]]]) 参数: thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。 arg1, arg2, ... 当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数
如果有兴趣想知道 Function.prototype.bind() 内部长什么样以及是如何工作的,这里有个非常简单的例子:
Function.prototype.bind = function (scope) { var fn = this; return function () { return fn.apply(scope); }; }
MDN为没有自身实现bind() 方法的浏览器提供了一个绝对可靠的替代方案:
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; }