2009-12-01 71 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冲突。