2009-12-01 74 views
33

我爲我的頁面添加了一個簡單的.js文件,其中有一些漂亮的常見任務類型的功能添加到ObjectArray原型。JavaScript中的原型對象打破jQuery?

經過反覆試驗,我已經想通了,添加任何功能Object.prototype,無論它的名字還是它做什麼導致Javascript錯誤在jQuery的:

的罪魁禍首?

Object.prototype.foo = function() { 
    /*do nothing and break jQuery*/ 
}; 

我得到的jquery-1.3.2.js線1056,在ATTR錯誤:函數{}聲明:

/*Object doesn't support this property or method*/ 
name = name.replace(/-([a-z])/ig, function(all, letter) { 
      return letter.toUpperCase(); 
     }); 

顯然G.replace是不確定的。

雖然很明顯,我只是沒有用原型來包裝我的頭,但我很失敗地弄清楚它是什麼。

要清楚,我不是在尋找解決方法,我已經處理了...我在尋找的是的答案爲什麼?。爲什麼向Object.prototype添加函數會破壞這段代碼?

+3

如果切換到完整的jquery文件(非縮小),您可能會得到更有意義的錯誤。這樣你就可以更清楚地看到哪些代碼有問題。 – 2009-12-01 16:53:27

+0

這是一個已知的bug:http://dev.jquery.com/ticket/2721 – 2009-12-01 17:27:19

+0

@ CrescentFresh的鏈接已過時。更新:https://bugs.jquery.com/ticket/2721 – WoodrowShigeru 2017-08-19 10:41:02

回答

19

你永遠不應該延長Object.prototype。它遠不止於jQuery;它完全打破了Javascript的「對象 - 哈希表」功能。不要這樣做。

你可以問約翰Resig,他會告訴你same thing

+19

擴展'Object.prototype'很好。需要注意的是在'for..in'循環中使用'hasOwnProperty'。自2.0以來,它在各種主流瀏覽器中都得到支持。 jQuery沒有在'for..in'循環中執行它只是懶惰。性能影響可以忽略不計,Resig知道這一點:http://osdir.com/ml/jquery-dev/2009-02/msg00543.html只是我的看法。 – 2009-12-01 17:28:14

+0

有趣的東西。謝謝。我不知道爲什麼它打破了「對象作爲哈希表」的東西......嗯。 – 2009-12-01 17:43:05

+3

@新月它比這更深。當然你可以用'for ... in'循環來解決這個問題,但是在Javascript中使用object-as-hashtables可以做很多其他的事情。例如,'toString','valueOf'等都沒有枚舉。這*會產生影響。另外,當你是一個被大量人使用的圖書館的主要開發者時,你不能責怪他關於懶惰的決定。我認爲一個更好的詞將是謹慎的。 – 2009-12-01 18:04:28

-1

我懷疑向Object.prototype添加一個函數直接打破jQuery。只要確保每一個for..in循環,你必須在你的網站被包裹在一個hasOwnProperty檢查,因爲你已經添加全局函數並遍歷它可以是不可預知的結果:

Object.prototype.foo = function() {};  
var myObject = {m1: "one", m2: "two" }; 

for(var i in myObject) { if(myObject.hasOwnProperty(i)) { 
    // Do stuff... but not to Object.prototype.foo 
}} 
+0

好吧,如果我註釋掉Object.prototype.foo聲明,一切正常。另外,在它突破的時候,它甚至還沒有達到超出foo聲明的任何代碼。 – 2009-12-01 17:04:26

+1

你是對的,它不直接打破jQuery,它打破了Javascript! – 2009-12-01 17:16:55

+0

取決於你如何看待它。理想情況下,您應該可以擴展Object而不會造成任何問題,但實際上,這是一個糟糕的主意,很少有很好的理由。 Crockford將枚舉函數添加到原型中,認爲它是「語言中的錯誤」,所以最好的做法是防守,並且總是將hasOwnProperty添加到for..in循環中。它很糟糕,但我會虔誠地做它;) – jshalvi 2009-12-01 18:25:43

5

我同意,爲Object.prototype添加一些內容需要謹慎,應該避免。尋找其他解決方案,如:

將其添加到Object,然後根據需要使用callapply進行訪問。 例如:

Object.foo = function() { return this.whatever()} 

然後調用該對象由:

Object.foo.call(Objname); // this invokes the function as though it were a 
          // method of Objname. That is, its like Objname.foo() 

爲了好玩,你可以添加以下(是的,我知道它有點危險......):

Function.using = Function.call; // syntactic sugar 

現在你可以寫Object.foo.using(Objname)它看起來像一個轉折。但是通常,不要改變任何大型原型。

34

如果它只是一個混亂的情況下......在循環中,你不能使用Object.defineProperty添加你的FN而不使它枚舉?

所以:

Object.defineProperty(Object.prototype, "foo", { 
    value: function() { 
     // do stuff 
    }, 
    enumerable : false 
}); 

似乎爲我工作。這仍然被認爲是不好的形式?

+1

我不知道......很高興知道它是否是錯誤的形式,但這對我來說很好。 – DataHerder 2011-08-05 23:59:46

+2

你可以,但是..in循環被設計成枚舉原型擴展。這就是你探索原型鏈的方式。它不會中斷for循環,它會打破盲目的代碼,盲目地假定迭代值總是具有某種類型,然而,因爲Object.prototype鏈可以包含函數,所以大括號之間的代碼可以在出現異常時引發異常他們只期望標量和對象。 – 2012-02-02 19:22:43

+0

它的工作原理沒有定義枚舉:Object.defineProperty(Object.prototype,「foo」,{ value:function(){} });' – 2012-09-23 14:34:03

0

我撞了我的腦袋解決這個問題,因爲我想實現我的所有對象的「真實」的面向對象,像這樣:

interface Object 
{ 
    GetType:() => string; 
    ToString:() => string; 
    GetHashcode:() => number; 
    Equals: (obj: any) => boolean; 
} 

自Object.prototype中打破了jQuery,我默認爲上述解決方案使用defineProperty,但不包含任何參數。

好消息是,你可以入侵defineProperty並實際接受參數。這是我的實現:

Object.defineProperty(Object.prototype, "Equals", 
    { 
     value: function (obj: any) 
     { 
      return obj == null && this == null 
        ? true 
        : obj != null && this == null 
         ? false 
         : obj == null && this != null 
          ? false 
          : this.GetHashcode() == obj.GetHashcode(); 
     }, 
     enumerable: false 
    }); 

這個工作,並沒有與JQuery衝突。