在我們需要在一個對象后多次進(jìn)行訪問控制訪問和上下文,代理模式是非常有用處的。
當(dāng)實(shí)例化一個對象開銷很大的時候,它可以幫助我們控制成本,提供更高級的方式去關(guān)聯(lián)和修改對象,就是在上下文中運(yùn)行一個特別的方法。
在jQuery核心中,一個jQUery.proxy()方法在接受一個函數(shù)的輸入和返回一個一直具有特殊上下文的新的實(shí)體時存在。這確保了它在函數(shù)中的值時我們所期待的的值。
一個使用該模式的例子,在點(diǎn)擊事件操作時我們利用了定時器。設(shè)想我用下面的操作優(yōu)先于任何添加的定時器:
$( "button" ).on( "click", function () {
// 在這個函數(shù)中,'this'代表了被當(dāng)前被點(diǎn)擊的那個元素對象
$( this ).addClass( "active" );
});
如果想要在addClass操作之前添加一個延遲,我們可以使用setTiemeout()做到。然而不幸的是這么操作時會有一個小問題:無論這個函數(shù)執(zhí)行了什么在setTimeout()中都會有個一個不同的值在那個函數(shù)中。而這個值將會關(guān)聯(lián)window對象替代我們所期望的被觸發(fā)的對象。
$( "button" ).on( "click", function () {
setTimeout(function () {
// "this" 無法關(guān)聯(lián)到我們點(diǎn)擊的元素
// 而是關(guān)聯(lián)了window對象
$( this ).addClass( "active" );
});
});
為解決這類問題,我們使用jQuery.proxy()方法來實(shí)現(xiàn)一種代理模式。通過調(diào)用它在這個函數(shù)中,使用這個函數(shù)和我們想要分配給它的this,我們將會得到一個包含了我們所期望的上下文中的值。如下所示:
$( "button" ).on( "click", function () {
setTimeout( $.proxy( function () {
// "this" 現(xiàn)在關(guān)聯(lián)了我們想要的元素
$( this ).addClass( "active" );
}, this), 500);
// 最后的參數(shù)'this'代表了我們的dom元素并且傳遞給了$.proxy()方法
});
jQuery代理方法的實(shí)現(xiàn)如下:
// Bind a function to a context, optionally partially applying any
// arguments.
proxy: function( fn, context ) {
if ( typeof context === "string" ) {
var 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
var args = slice.call( arguments, 2 ),
proxy = function() {
return fn.apply( context, args.concat( 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 || proxy.guid || jQuery.guid++;
return proxy;
}
更多建議: