2

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

// 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 奇怪的行为

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

“错误”不会发生在:Chrome 29.0.1547.66m、Opera 12.16

4

2 回答 2

2

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

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

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

因此,在您的用户脚本window.$ === undefined中,在实际页面中,它被定义为 mootools 助手。unsafewindow.$也是 mootools 的助手,就像unsafeWindowunwrapped page一样window

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

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

更新:GreasemonkeycreateSandox()通过设置在它们的“无授权”分支中主动禁用这些包装器wantXRays = false。我认为这是一个错误

现在,这就是您.noConflict()首先需要GM.

var $ = $.noConflict()无法工作,因为这是一个错误。将var $被提升,因此它立即未定义。jQuery 不会实际设置它(它只是设置window.$,而不是 local-scope $),因此$.noConflict()调用变为undefined.noConflict().

于 2013-09-06T20:03:40.100 回答
0

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

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

将该$.noConflict()行移入全局范围,您应该没问题:

$.noConflict();
(function() {
    ...
})();
于 2013-09-06T17:53:58.370 回答