在写一些jq插件时,往往需要在回调函数上下文中注入调用者对象,也就是改变函数上下文中 this 的引用。
从jQuery 1.4 开始便可以使用 jQuery.proxy 方法解决这个问题。

定义和用法

$.proxy 方法接受一个已有的函数,并返回一个带特定上下文的新的函数。
该方法通常用于向上下文指向不同对象的元素添加事件。

提示:如果您绑定从 $.proxy 返回的函数,jQuery 仍然可以通过传递的原先的函数取消绑定正确的函数。

语法

// 1
$(selector).proxy(function,context);
// 2
$(selector).proxy(context,name);

实例

// 用例1
var obj1 = function(){
this.txt = "helloWorld";
$(document).click(this.fn);
};
var obj2 = function(){
this.txt = "helloWorld";
$(document).click($.proxy(this.fn, this));
};
obj1.prototype.fn = obj2.prototype.fn = function() {
console.log(this.txt);
};
var a = new obj1(); // undefined
var b = new obj2(); // helloWorld
// 用例2
var dialog = {
msg: 'helloWorld',
show: function () {
console.log(this);
console.log(this.msg);
}
}
$(document).click(dialog.show);
// #document
// undefined
$(document).click($.proxy(dialog, "show"));
// Object {msg: "helloWorld", show: function}
// helloWorld

未使用 jQuery.proxy 方法时,click 方法中 this 指向为执行 click 方法的 jQuery 对象;
使用 jQuery.proxy 方法时,click 方法中 this 指向为你所期望的对象。

原理

不难猜出其底层实现应该是原生 js 中的 call 或 apply 方法。

jquery1.9 中的源码片段:

proxy: function( fn, context ) {
var args, proxy, tmp;
if ( typeof context === "string" ) {
tmp = fn[ context ];
context = fn;
fn = tmp;
}
// Quick check to determine if target is callable, in the spec
// this throws a TypeError, but we will just return undefined.
if ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// Simulated bind
args = core_slice.call( arguments, 2 );
proxy = function() {
return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
};
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
return proxy;
}