我有一个包含以下内容的用户脚本:
// userscript header
(function() {
// here is jquery source code
var $ = $.noConflict();
})();
我正在使用的网站正在使用mootools,因此网站的代码取决于$
。由于一些奇怪的原因,noConflict
在Firefox(23.0.1)中没有帮助。该网站仍然以$获取jQuery,这打破了网站的原始功能。
但是,当我将其更改为: var $ = jQuery.noConflict();
有效。为什么呢?
我不能将用户脚本放在jsfiddle上,所以这里有一个包含所有代码的gif(左边的HTML,右边的用户脚本),显示问题:
版本:一切都是最新的,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
答案 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 = false
在createSandox()
的“无授权”分支中明确禁用这些包装。我认为这是a bug。
现在,这就是.noConflict()
中首先需要GM
的原因。
var $ = $.noConflict()
无法正常工作,因为它是一个错误。 var $
将被悬挂,因此立即未定义。 jQuery实际上不会设置它(它只设置window.$
,而不是本地范围$
),因此$.noConflict()
调用变为undefined.noConflict()
。
答案 1 :(得分:0)
我对jQuery的noConflict()
方法不太熟悉,但我想它必须在全局范围内使用。
您在匿名函数的范围内使用它,因此noConflict()
方法不会对此范围之外的$
声明产生任何影响。
将$.noConflict()
行移动到全局范围内,您应该没问题:
$.noConflict();
(function() {
...
})();