jQuery.noConflict用户脚本中的奇怪行为,仅限Firefox

时间:2013-09-06 17:48:32

标签: jquery firefox mootools greasemonkey userscripts

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

// userscript header
(function() {
    // here is jquery source code
    var $ = $.noConflict();
})();

我正在使用的网站正在使用mootools,因此网站的代码取决于$。由于一些奇怪的原因,noConflict在Firefox(23.0.1)中没有帮助。该网站仍然以$获取jQuery,这打破了网站的原始功能。

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

有效。为什么呢?

我不能将用户脚本放在jsfiddle上,所以这里有一个包含所有代码的gif(左边的HTML,右边的用户脚本),显示问题:

jQuery.noConflict weird behavior

版本:一切都是最新的,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

2 个答案:

答案 0 :(得分:2)

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

if ( window.$ === jQuery ) {
  window.$ = _$; // where $_ is window.$ before jquery reassigns it.
}

现在我们需要记住,用户脚本操作的window实际上与网站看到的window不同。它是一个沙盒包装器(至少在Greasemonkey和Scriptish中)。该包装器实际上隐藏了所有“expandos”,即在原始对象上添加或覆盖的属性。

因此,在您的用户脚本window.$ === undefined中,在实际页面中,它被定义为mootools帮助程序。 unsafewindow.$也是mootools的助手,因为unsafeWindow是未展开的网页window

现在,当您的用户脚本包含jQuery时,$将在包装的window上设置。从网站的角度来看,原始页面window.$仍然是模仿者。

接下来,如上所述,对.noConflict()的调用将恢复window.$,但是在沙盒包装器上。因此,用户脚本沙箱中的window.$再次变为undefined,而用户脚本沙箱中的页面window.$(又名。unsafeWindow.$)仍然是moo帮助程序(并且是实际上从未改变过。)

更新:Greasemonkey通过设置wantXRays = falsecreateSandox()的“无授权”分支中明确禁用这些包装。我认为这是a bug

现在,这就是.noConflict()中首先需要GM的原因。

var $ = $.noConflict()无法正常工作,因为它是一个错误。 var $将被悬挂,因此立即未定义。 jQuery实际上不会设置它(它只设置window.$,而不是本地范围$),因此$.noConflict()调用变为undefined.noConflict()

答案 1 :(得分:0)

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

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

$.noConflict()行移动到全局范围内,您应该没问题:

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