奇怪的Chrome原型/ jQuery冲突

25
我们有一个应用程序,它依赖于 prototype 的遗留代码,但我们发现在大多数我们想要使用它的地方,prototype 过于“沉重”,而且我们发现 jQuery 更适合我们的工作方式。因此,我们正在将新功能迁移到 jQuery。
与此同时,我们有几个页面需要加载这两个库:
<script language="javascript" type="text/javascript"
        src="prototype-1.5.1.2.js"></script> 
<script language="javascript" type="text/javascript"  
        src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script> 

(请注意,这是旧版的prototype,我们发现了升级时不想修复的问题,无论如何,我们正在逐步淘汰它)

在IE6、IE7、IE8-as-7和FX3中可以正常工作,但在Chrome中加载后,所有jQuery相关的内容都失败了。

打开开发人员JavaScript控制台会显示以下错误消息:

Uncaught Error: NOT_SUPPORTED_ERR: DOM Exception 9 http://.../prototype-1.5.1.2.js (line 1272)
Uncaught TypeError: Object #<an Object> has no method 'ready' http://.../lib.js (line 161)
Uncaught TypeError: Object #<an Object> has no method 'slideUp' http://.../page.aspx (line 173)
... and so on - all the failures are missing jQuery methods

看起来是原型中的冲突导致创建jQuery对象失败。

具体的原型问题似乎是Prototype.BrowserFeatures.XPath为true,而实际上不应该是这样的,因为XPath document.evaluate不被支持。

好了,现在 打开javascript控制台重新加载页面——一切正常! 怎么回事?关闭控制台后,重新加载又失败了。

仅在页面载入时没有打开javascript控制台时才会出现这种错误,这有点像Chrome的一个bug。

有人能解释出错的原因吗?为什么原型中的错误会导致jQuery初始化失败?为什么在打开控制台时页面可以正常工作?

有人知道一个好的解决方法吗?(除了升级到prototype-1.6.0.3.js,这个修复了这个问题,但在其他地方会破坏很多遗留代码)

2个回答

45

Core/jQuery.noConflict

注意:必须在包含jQuery javascript文件之后,但包含任何其他冲突库之前调用此函数,并且在实际使用那些其他冲突库之前调用,以防jQuery最后被包含。noConflict可以在jQuery.js文件的末尾调用,以全局禁用$() jQuery别名。jQuery.noConflict返回一个对jQuery的引用,因此它可以用于覆盖jQuery对象的$()别名。

也许尝试更改为:

<script language="javascript" type="text/javascript"
  src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script>
<script language="javascript" type="text/javascript"
  src="prototype-1.5.1.2.js"></script>

可以,谢谢。你知道为什么 Chrome 控制台也能修复它吗? - Keith
11
使用任何类型的调试工具(特别是浏览器内置的JavaScript调试工具)都会导致代码以不同的方式执行,“我们所观察到的不是自然本身,而是自然暴露在我们提问方法下的状态。”(海森堡,《物理学与哲学》,1963)。另外,不要忘记接受我的答案! - Jake McGraw
+1 这也对我有帮助。我想指出有一些相互矛盾的文档,所以要小心:http://docs.jquery.com/Using_jQuery_with_Other_Libraries - blu
这并不总是适用的,很多时候你无法控制页面中的脚本,比如说,如果你创建了某种第三方服务,用户将其添加到他们的网站/博客中。 - vsync

10
我发现这个问题的根源在于:
  1. Prototype被加载,因为WebKit缺少document.getElementsByClass(),Prototype(隐蔽地)创建了它。

  2. jQuery初始化开始,在顶部,它将window.$设置为jQuery

  3. 在JQuery的初始化过程中,Sizzle引擎(在1.3.2中添加)初始化。作为其内省的一部分,它检查并测试document.getElementsByClass()的功能。结果,它调用了Prototype的getElementsByClass()实现,它依赖于window.$被设为Prototype的$,而不是jQuery的。

最终,这将需要在jQuery中修复(请参见票证http://bugs.jquery.com/ticket/43655027)。我的快速修补是删除jQuery初始化顶部的window.$赋值。


这确实是问题。正如某位在工单中提到的那样,有一部分代码可以用try/catch包裹起来以避开这个问题。 - vsync

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接