JavaScript 代理模式

2018-08-02 16:27 更新

代理模式

在我們需要在一個(gè)對(duì)象后多次進(jìn)行訪問(wèn)控制訪問(wèn)和上下文,代理模式是非常有用處的。

當(dāng)實(shí)例化一個(gè)對(duì)象開(kāi)銷很大的時(shí)候,它可以幫助我們控制成本,提供更高級(jí)的方式去關(guān)聯(lián)和修改對(duì)象,就是在上下文中運(yùn)行一個(gè)特別的方法。

在jQuery核心中,一個(gè)jQUery.proxy()方法在接受一個(gè)函數(shù)的輸入和返回一個(gè)一直具有特殊上下文的新的實(shí)體時(shí)存在。這確保了它在函數(shù)中的值時(shí)我們所期待的的值。

一個(gè)使用該模式的例子,在點(diǎn)擊事件操作時(shí)我們利用了定時(shí)器。設(shè)想我用下面的操作優(yōu)先于任何添加的定時(shí)器:

$( "button" ).on( "click", function () {
  // 在這個(gè)函數(shù)中,'this'代表了被當(dāng)前被點(diǎn)擊的那個(gè)元素對(duì)象
  $( this ).addClass( "active" );
});

如果想要在addClass操作之前添加一個(gè)延遲,我們可以使用setTiemeout()做到。然而不幸的是這么操作時(shí)會(huì)有一個(gè)小問(wèn)題:無(wú)論這個(gè)函數(shù)執(zhí)行了什么在setTimeout()中都會(huì)有個(gè)一個(gè)不同的值在那個(gè)函數(shù)中。而這個(gè)值將會(huì)關(guān)聯(lián)window對(duì)象替代我們所期望的被觸發(fā)的對(duì)象。

$( "button" ).on( "click", function () {
  setTimeout(function () {
    // "this" 無(wú)法關(guān)聯(lián)到我們點(diǎn)擊的元素
    // 而是關(guān)聯(lián)了window對(duì)象
    $( this ).addClass( "active" );
  });
});

為解決這類問(wèn)題,我們使用jQuery.proxy()方法來(lái)實(shí)現(xiàn)一種代理模式。通過(guò)調(diào)用它在這個(gè)函數(shù)中,使用這個(gè)函數(shù)和我們想要分配給它的this,我們將會(huì)得到一個(gè)包含了我們所期望的上下文中的值。如下所示:

$( "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;
 }
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)