2011-03-18 86 views
0

我無法從Post.success函數中調用this.RenderDeals()。我認爲這與範圍有關?有人可以解釋這個問題,並可能提出一種解決方法。我嘗試過使用原型和模塊模式,都沒有任何運氣。Javascript class scope

FYI Post是一個返回jQuery Deferred對象的$ .ajax包裝器。

function Deals() { 
     this.template = '#trTemplate'; 
     this.container = '#containerTable'; 
     this.GetDeals = function() { 
      Post('Deal.svc/GetDeals') 
      .success(function (result) { 
       this.RenderDeals(result); 
      }); 
     }; 
     this.RenderDeals = function (deals) { 
      $(this.template).tmpl(deals).appendTo(this.container); 
     } 
    } 


    var deal = new Deals(); 
    deal.GetDeals(); 

UPDATE:

好了,所以我加了下面的行正上方GetDeals功能:

var me = this; 

,而是叫

me.RenderDeals(result); 

看似正常工作,但我不知道爲什麼。

+0

這是因爲你已經定義'我'然後使用它。但直接使用'this'會給你一個別的事情的例子,因爲你處於不同的上下文/範圍中。 – Kon 2011-03-18 23:56:42

+0

只是一個僅供參考的東西,在javascript成語中,一個以大寫字母開頭的函數意味着它是一個構造函數。沒有問題或任何東西,但它看起來很奇怪的人是一個JavaScript的人,但不是一個.net人 – 2011-03-18 23:56:51

+0

@Matt也許我會開始一場革命...... – 2011-03-19 00:34:24

回答

5

在你的 「成功」 功能this參考幾乎肯定是不是你t它是。試試這個變化:

function Deals() { 
    var instance = this; 

    this.template = '#trTemplate'; 
    this.container = '#containerTable'; 
    this.GetDeals = function() { 
     Post('Deal.svc/GetDeals') 
     .success(function (result) { 
      instance.RenderDeals(result); 
     }); 
    }; 
    this.RenderDeals = function (deals) { 
     $(this.template).tmpl(deals).appendTo(this.container); 
    } 
} 

通過隱藏在「實例」變量this參考,您的處理器將具有調用其他功能(「RenderDeals」)時,又回到了相關實例的方式保證。

+1

yay關閉! +1 – 2011-03-18 23:53:13

+1

關閉。我會閱讀。 – 2011-03-18 23:57:23

0

爲什麼不在Deals()之外定義RenderDeals()?

function RenderDeals(dealsObj, dealsData) { 
     $(dealsObj.template).tmpl(dealsData).appendTo(dealsObj.container); 
    } 

然後,而不是這樣的:

this.RenderDeals(result); 

這樣做:

RenderDeals(this, result); 
+0

因爲我試圖封裝功能在一個類。 – 2011-03-18 23:52:27

+0

也許他不希望它是全球可見的? – Pointy 2011-03-18 23:53:08

+0

對不起,這並不明顯,因爲它沒有在問題中指定。 – Kon 2011-03-18 23:57:00

0

試試這個:

var Deals = { 
    template: $('#trTemplate'), 
    container: $('#containerTable'), 
    init: function(){ 
     return Deals; 
    } 
    GetDeals: function() { 
     Post('Deal.svc/GetDeals') 
     .success(function (result) { 
      Deals.RenderDeals(result); 
     }) 
    }, 
    RenderDeals = function (deals) { 
     Deals.template.tmpl(deals).appendTo(Deals.container); 
    } 
} 

var deal = Deals.init(); 
deal.GetDeals(); 
+0

也許他真的想要構建許多這樣的實例。 – Pointy 2011-03-18 23:53:41

+0

這會起作用,但通過使用閉包來捕獲這個值,imo尖端有更好的答案。 – 2011-03-18 23:54:13

+0

是的,這是有道理的 – Adam 2011-03-18 23:55:32

0

你是對的,這是一個範圍界定問題。波蒂有正確的答案,但我認爲我可以填補一些正在發生的事情。

this在JavaScript中是一個隱式變量,它被設置爲默認情況下函數所附加的任何內容(或者全局對象,如果它不附加任何東西)。當您將函數作爲參數傳遞給Post#成功時,它不會附加到任何實例,更不用說當前的Deals實例。

Pointy在這裏有最好的答案,他正在做的是創建一個顯式變量,捕獲交易的隱含變量this。 javascript最酷的功能之一是,函數定義範圍內的所有內容都將在函數調用的範圍內,因此通過創建該變量,您可以稍後再次訪問它,無論何時何地匿名函數是調用。

2

首先,在javascript中沒有類,只有對象。這聽起來很奇怪,但是你仍然可以在沒有javascript的情況下做OOP :)我建議你閱讀這個。

你對範圍問題是正確的,this關鍵字有一些奇怪的行爲。請閱讀this瞭解更多信息。

使用任何函數對象的prototype屬性進行研究。我喜歡做我的javascript以下列方式OOP:

function Deals(){ 
    //this is your constructor 
    var me = this; 
    //this way you can avoid having to search the DOM every time you want to reference 
    //your jquery objects. 
    me.template = $('#trTemplate'); 
    me.container = $('#containerTable'); 
} 
Deals.prototype.getDeals = function(){ 
    var me = this; 
    Post('Deal.svc/GetDeals') 
    .success(function (result) { 
     me.RenderDeals(result); 
    }) 
} 
Deals.prototype.renderDeals = function(){ 
    var me = this; 
    me.template.tmpl(deals).appendTo(me.container); 
} 

通過在每個原型函數的頂部聲明var me = this;,您可以創建一個指向感興趣的對象封閉,甚至內部的回調:)

+0

哦,是的,忘了提到你會使用這樣的Deals對象:'var deals = new Deals(); deals.renderDeals();' – Hersheezy 2011-03-19 00:04:52

+0

感謝您的替代模式。說實話,我不知道我是否真的需要這樣做。我永遠不會需要這個對象的許多實例,我只是試圖封裝一個特定的頁面功能,使它更清潔,更易於管理。 – 2011-03-19 00:26:22