2012-01-24 126 views
0

我想在點擊處理程序中使用fnB。有沒有優雅的解決方案?謝謝。基於SoWeLie的回答從jQuery'closure'訪問外部方法

A = function() { 
    ... 
} 

B = function() { 
    ... 
} 
B.prototype = new A(); 
B.prototype.fnB = function() {} 
B.prototype.fn = function() { 
    // this isntanceof B -> true 
    jQuery(selector).click(function() { 
    this.fnB() // this instance of B -> false, this == $(selector) -> true 
    } 
} 

實現:

EventType = { 
    ButtonClicked: 0 
    ... 
} 

function Delegate(object, method) { 
    return function() { method.apply(object, arguments); } 
} 

function Observable() { 
    this._eventHandlers = {}; 
} 

Observable.prototype = { 
    addListener: function(eventType, listener) { 
     if(!this._eventHandlers.eventType) { 
      this._eventHandlers.eventType = []; 
     } 
     this._eventHandlers.eventType.push(listener); 
    }, 

    removeListener: function(eventType, listener) { 
     if(this._eventHandlers.eventType) { 
      for(var i = this._eventHandlers.eventType.length; --i > -1;) { 
       if(!listener || this._eventHandlers.eventType[i] == listener) { 
        this._eventHandlers.eventType.splice(i, 1); 
       } 
      } 
     } 
    }, 

    fireEvent: function(eventType, data) { 
     if(this._eventHandlers.eventType) { 
      for(var i = 0; i < this._eventHandlers.eventType.length; ++i) { 
       var handleEvent = this._eventHandlers.eventType[i]; 
       if(handleEvent) { 
        handleEvent(this, data); 
       } 
      } 
     } 
    } 
} 

Dialog.Buttons = { ButtonOk: 0, ButtonCancel: 1, ButtonYes: 2, ButtonNo: 3, ButtonClose: 4 }; 
Dialog.prototype = new Observable(); 
Dialog.prototype.bindEvents = function() { 
    $('#dlgButtonOk', this._$el).click(Delegate(this, function() { 
     this.fireEvent(EventType.ButtonClicked, Dialog.Buttons.ButtonOk); 
    })); 
    $('#dlgButtonCancel', this._$el).click(this, function() { 
     this.fireEvent(EventType.ButtonClicked, Dialog.Buttons.ButtonCancel); 
    }); 

$(function() { 
    dialog = new Dialog('.dialogWnd') 
    dialog.addListener(EventType.ButtonClicked, function() {alert(1)}) 
}); 

???? 哎呀!您的編輯無法提交,因爲:

您的帖子沒有太多的上下文來解釋代碼段;請更清楚地解釋你的情況。 ???

回答

1

最優雅的解決方案是使用應用功能的方法:

var hitch = function (scope, callback) { 
     return function() { 
      return callback.apply(scope, Array.prototype.slice.call(arguments)); 
     } 
    } 

更改您的代碼如下所示:

jQuery(selector).click(hitch(this, function() { 
    this.fnB() // this instance of B -> false, this == $(selector) -> true 
    })) 

注意調用匿名函數,這將確保在點擊處理程序中保留應付。

+0

我發現了一個解決方案,基本上和你基於代表(在C#中使用)一樣:http://odetocode.com/Blogs/scott/archive/2007/07/04/javascripts-slippery-this-reference-和其他妖怪,在最closet.aspx。非常感謝。 – DraganS

+0

是的,這正是我的代碼所做的。 – SoWeLie

1
var that = this; 
jQuery(selector).click(function() { 
    that.fnB() 
} 

或者您可以使用bind,但它尚未得到廣泛支持。

0

只需使用一個封閉:

B.prototype.fn = function() { 
    // this isntanceof B -> true 
    var that = this; 
    jQuery(selector).click(function() { 
     that.fnB(); 
    }); 
}; 
+0

我不喜歡它,但它可能是JS中唯一可能的解決方案。謝謝。 – DraganS