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

标签 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

最佳答案

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

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

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

因此,在您的用户脚本中 window.$ === undefined 而在实际页面中,它被定义为 mootools 助手。 unsafewindow.$ 也是 mootools 助手,如 unsafeWindow是展开的页面窗口

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

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

更新:Greasemonkey 在 createSandox() 的“no-grants”分支中显式主动禁用这些包装器通过设置 wantXRays = false。我认为这是 a bug .

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

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

关于jQuery.noConflict 用户脚本中的奇怪行为,仅在 Firefox 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18663650/

相关文章:

javascript - 为什么我不能使用 MooTools 设置我的输入字段?

javascript - 订阅 jQuery.ajax() 成功事件

javascript - 更改 Firefox 输入文件标签中的光标样式

javascript - 使用固定的左 div 水平滚动

javascript - 在 Canvas 中绘制完整尺寸的图像仅在 Mozilla Firefox 中第二次尝试时有效

html - 我可以只为 firefox 编写打印样式吗?

javascript - onHashChange running onLoad...尴尬

javascript - Rails 没有为 JavaScript 请求选择正确的布局

javascript - JQuery - 未捕获的语法错误 : Unexpected identifier

javascript - 外部 JS 文件 + jquery + css