2011-05-04 51 views
3

我不得不爲一個我上傳的網站修復megamenu系統,而且我遇到了一個bug。javascript:在對象字面量函數中使用'this'給出一個錯誤

DOM準備就緒(包含jQuery)後,運行megamenu的渲染函數。在這裏有一個監聽器被添加到resize來重新運行這個函數,重新渲染代碼。然而,我得到的JavaScript錯誤,認爲這個渲染函數,當從對象內部調用時,實際上是一個窗口的函數,所以我得到「Uncaught TypeError:對象[對象DOMWindow]沒有方法'渲染'」

但是函數仍然運行!

這裏是代碼的簡單快照:

var jkmegamenu= 
{ 
... 
    render:function($) 
    { 
    ... 
     $(window).bind("resize", function() 
     { 
      this.render($); 
     } 

    } 

} 

現在,我已經試過jkmegamenu.render($)(不知道美元是什麼,有無因jQuery的原理我想象),並且我已經試圖將自己定義爲self:這個但是會發生同樣的錯誤。它是一個相當大的文件,我很忙,所以我只考慮重新編碼一個合適的jQuery對象(例如http://www.phpied.com/3-ways-to-define-a-javascript-class/),如果這是唯一的其他選項,否則有人知道一個快速修復?

該網站是kent.ac.uk,你將能夠看到彈出的錯誤,特別是在調整大小。

回答

5

在JavaScript this是有點不同的比你可從如C++,C#或Java的一些其他語言習慣。它完全由定義,函數的定義如何稱爲,而不是這裏更多:You must remember this

在你的情況,如果你想確保this指的是你jkmegamenu例如,你可以使用jQuery的proxy功能,這將創建一個閉合的在你身後的幕後,與調用你的函數正確的 「上下文」(this值):

var jkmegamenu= 
{ 
... 
    render:function($) 
    { 
    ... 
     $(window).bind("resize", $.proxy(function() 
     { 
      this.render($); 
     }, this)); 
    } 

} 

,或直接使用自己的關閉:

var jkmegamenu= 
{ 
... 
    render:function($) 
    { 
    ... 
     var inst = this; // Remember `this` 
     $(window).bind("resize", function() 
     { 
      // Use it 
      inst.render($); 
     }); 
    } 

} 

...其優點是可以使用this來引用您將事件處理程序掛接到的DOM對象(好吧,對window的用處不大,但在綁定到其他對象時非常有用)。

閉包是處理事件的非常有用的方式。更多在這裏:Closures are not complicated

對於你的情況,因爲jkmegamenu是單身,我可能只是使用模塊模式,而不是擔心this可言:

var jkmegamenu = (function() { 
    var inst = {}; 

    // ... 

    inst.render = jkmegamenu_render; 
    function jkmegamenu_render($) 
    { 
     $(window).bind("resize", function() 
     { 
      inst.render($); 
      // Or just jkmegamenu_render($); 
     }); 
    } 

    // Could have some private functions here, just by 
    // virtue of not adding them to `inst` 

    // ... 

    return inst; 
})(); 

這有也給你的優勢功能名稱,其中helps your tools help you,並讓您擁有真正的私人功能。

你也可以將這個模式應用到工廠函數(有些人會稱它們爲「類」,儘管JavaScript沒有類),只是稍微調整一下。

3

Javascript的行爲與你期望的略有不同,因爲'this'指的是它當前所處的任何功能範圍。所以'this'並不指向你所期望的。相反,使用:

var jkmegamenu= 
{ 
... 
    render:function($) 
    { 
    ... 
     var that = this; 
     $(window).bind("resize", function() 
     { 
      that.render($); 
     } 
    } 
} 
+1

JavaScript是**不**損壞。它的作用*不同於你以前的習慣,但那不是*破碎*。 – 2011-05-04 12:57:59

+0

我承認,破碎可能有點嚴厲,但很多人認爲JavaScript不應該這樣。如果您閱讀'Javascript:The Good Parts',道格拉斯克羅克福德(和其他一些人一樣)提出了同樣的要求。我會改變我的措辭,但如果它錯誤的人:) – Igor 2011-05-04 13:01:46

+0

Crockford提出了很多的要求。其中一些非常好。有些不是。我總是說讀克羅克福德很重要 - 然後得出你自己的結論。 ;-)我非常喜歡JavaScript提供的自由和靈活性。 – 2011-05-04 13:04:09

相關問題