jQuery.noConflict仅在Firefox中的userscript中存在奇怪的行为

jQuery.noConflict仅在Firefox中的userscript中存在奇怪的行为,jquery,firefox,mootools,greasemonkey,userscripts,Jquery,Firefox,Mootools,Greasemonkey,Userscripts,我有一个包含以下内容的用户脚本: // userscript header (function() { // here is jquery source code var $ = $.noConflict(); })(); 我正在使用它的站点正在使用mootools,因此该站点的代码取决于$。由于某种奇怪的原因,noConflict在Firefox(23.0.1)中没有帮助。该站点仍然以美元为单位获取jQuery,这破坏了该站点的原始功能 但是,当我将其更改为: var$=jQ

我有一个包含以下内容的用户脚本:

// userscript header
(function() {
    // here is jquery source code
    var $ = $.noConflict();
})();
我正在使用它的站点正在使用mootools,因此该站点的代码取决于
$
。由于某种奇怪的原因,
noConflict
在Firefox(23.0.1)中没有帮助。该站点仍然以美元为单位获取jQuery,这破坏了该站点的原始功能

但是,当我将其更改为: var$=jQuery.noConflict()

它起作用了。为什么?

我无法将userscript放在JSFIDLE上,因此下面是一个包含所有代码的gif(HTML在左边,userscript在右边),显示了问题:

版本:一切都是最新的,Firefox 23.0.1,Greasemonkey 1.11,jQuery v1.10.2,Mootools 1.4.5-nc


“Bug”不会发生在:Chrome 29.0.1547.66m,Opera 12.16

我不太熟悉jQuery的
noConflict()
方法,但我认为它必须在全局范围内使用

您正在匿名函数的范围内使用它,因此
noConflict()
方法不会对该范围外的
$
声明产生任何影响

$.noConflict()
行移动到全局范围,您应该可以:

$.noConflict();
(function() {
    ...
})();

让我们看看
noConflict()
是如何实际实现的

if ( window.$ === jQuery ) {
  window.$ = _$; // where $_ is window.$ before jquery reassigns it.
}
现在我们需要记住,用户脚本操作的
窗口实际上与站点看到的
窗口不同。它是一个沙盒包装(至少在Greasemonkey和Scriptish中是这样)。该包装实际上隐藏了所有“expandos”,即原始对象上添加或覆盖的属性

因此,在用户脚本
窗口中,$==未定义的
,而在实际页面中,它被定义为mootools助手<代码>取消安全窗口。$
也是mootools帮助程序,打开的页面<代码>窗口
也是

现在,当您的用户脚本包含jQuery时,
$
将在包装的
窗口上设置为on。从网站的角度来看,原始页面
窗口。$
仍在使用

接下来,如上所述,对
.noConflict()
的调用将还原
窗口。$
返回,但在沙箱包装上。因此,用户脚本沙盒中的
窗口。$
再次变为
未定义的
,而页面
窗口。$
(又称
未安全窗口。$
在用户脚本沙盒中)仍然是moo助手(实际上从未更改)

更新:Greasemonkey通过设置
wantXRays=false
,在其“无授权”分支中显式禁用这些包装。我认为是这样。

现在,这就是为什么在
GM
中首先需要
.noConflict()


var$=$.noConflict()
无法工作,因为这是一个错误。
var$
将被提升,因此它将立即被取消定义。jQuery实际上不会设置它(它只是设置
窗口。$
,而不是本地范围
$
),因此
$.noConflict()
调用变得
未定义。noConflict()

您尝试过使用
jQuery
,而不是
$
?-<代码>jQuery.noConflict()
和使用jQuery的
jQuery
代替
$
没有任何效果。但当我将
window.$instanceof jQuery
(因为window.$实际上不是instance)更改为
window.$==jQuery
时,它确实有效。为什么会有这样的效果呢?所以
var$=jQuery.noConflict()
有效,而
var$=$.noConflict()
无效。有什么区别?呃,显然
jQuery==$
是错误的。我得研究一下……请多开几天。我也不知道为什么,而且可能是一些刚刚不在线的人提供了一些很好的信息。现在可以复制,并在GM中找到“负责”的代码片段(中的“无授权代码路径”)。目前还不知道为什么会发生这种情况。那不是在他将jQuery包括进去之前吗?“
(function(){//here is jquery source code
“原始站点的代码在包含我的用户脚本后崩溃(在最新的firefox+greasemonkey中,但在opera中不是),因此这句话并不总是正确的:“原始页面窗口。$从网站的角度来看仍然是mootools。”(或者我遗漏了什么?)是的,我就是这么说的(我用Firefox/Scriptish进行了测试)。如果没有实际的可复制示例或至少实际的错误消息,我无法深入挖掘。如果您想要答案,请相应地更新您的问题。我应该注意,我是Scriptish附加组件的合著者,因此我对GM/Scripish有一两点了解。我已经更新了问题,请检查。(我无法重现原始问题,因此我已使用类似于我可以重现的内容对其进行了更新。)如果我执行
var$=window.$.noConflict()
,那么它就可以工作了。所以我想你是对的。谢谢你的帮助。GM的“无补助金”行为是一个bug。它破坏了数千个脚本,给新手带来了不少麻烦,但同时却没有帮助任何人。然而,这是故意的!而且,通用汽车首席开发人员拒绝承认他的巨大错误。