【问题标题】:Is there a way to wrap jQuery's isArrayLike?有没有办法包装 jQuery isArray Like?
【发布时间】:2017-01-30 06:22:30
【问题描述】:

我正在尝试处理 XenForo 和基本插件之间的冲突。我也不能直接修改代码。 jQuery 1.11.3 是在用的版本,也不能升级。

我可以用 try/catch 包装调用函数并避免冲突,但真正的解决方法是用 try/catch 包装 jQuery 的 isArrayLike。

isArrayLike 位于https://github.com/jquery/jquery/blob/master/src/core.js#L464 中第 464 行的(当前版本)jQuery 源代码中

我需要抓住的似乎正是https://forum.jquery.com/topic/jquery-isarraylike-for-consistency 中关于 isArrayLike 在传递无效类型时引发错误的争论。

那么,既然 jQuery 的 isArrayLike 没有暴露出来,有没有办法把它包装起来,或者在最坏的情况下,进去替换它?

编辑:请注意,到目前为止,所有 cmets 都在尝试调试错误本身。那不是我的问题。我在问是否有任何方法可以访问 isArrayLike,所以它可以用另一个函数包装。

【问题讨论】:

  • 说明你需要在问题本身中捕捉到什么。那个论坛帖子太宽泛了。
  • 在邮件和警报弹出窗口悬停时,XenForo.ExtLoader 将 something 传递给 $.each(),而 $.each() 又调用 isArraylike,然后抛出 TypeError .我可以包装 XenForo.ExtLoader 以抑制错误并显示弹出窗口,但这将问题捕捉得太高了 - 弹出窗口最终无人居住。如果我能找到一种方法来包装 isArraylike 以捕获该 TypeError,我应该能够让 each() 仍然填充弹出窗口。
  • 导致 TypeError 的something 是什么?
  • 我不确定。但是由于它来自 Xen 发送的东西,并且错误是由 jQuery 触发的,所以我也没有能力直接修复错误的原因,因此需要在事后进行猴子补丁。
  • 如果通过将isArrayLike 的第一行var length = !!obj && "length" in obj && obj.length, 更改为var length = !!obj && "length" in Object(obj) && obj.length, 来修补jQuery,这能解决问题吗?请注意,我添加了 Object 调用。

标签: javascript jquery monkeypatching


【解决方案1】:

我建议替换 jQuery eachmap 方法,这似乎是调用 isArrayLike 的唯一方法,除了 makeArray。但是我建议的修复对于后一种方法不是必需的。

添加这个:

(function ($, origEach, origMap) {
    $.each = function (elems, callback, arg) {
        return origEach.call(this, Object(elems), callback, arg);
    };
    $.map = function (elems, callback, arg) {
        return origMap.call(this, Object(elems), callback, arg);
    };
})(jQuery, jQuery.each, jQuery.map);

它改变了传递给mapeach 的第一个参数:它被包装在一个Object 调用中,当它是一个数组时它不会改变任何东西,但如果它不是一个对象则将​​参数转换为一个对象一个对象(出于某种奇怪的原因)。

修补 jQuery

如果可以使用补丁版本的jQuery,只需存储一个jQuery的副本,并在函数isArrayLike中修改这一行:

var length = !!obj && "length" in obj && obj.length,

到:

var length = !!obj && "length" in Object(obj) && obj.length,

这对XenForo 来说应该不是问题,只要您通过另一个script 标签显式添加修补的jQuery, 包含XenForo。最新的 jQuery 对象会覆盖之前的对象,因此 XenForo 也将使用已修补的版本,即使它本身包含未修补的 jQuery 库。

修补的缺点是您无法升级 jQuery(隐式使用 XenForoupgrade),除非您每次升级时都对其进行修补(直到不再需要的版本)。

这是第一个解决方案不会遇到的问题。

【讨论】:

  • 接近了,但还是太高了。看起来好像 isArraylike 被传递了一个空字符串而不是一个对象。 isArraylike should 的第一行可以捕捉到这一点,但它在查找 obj.length 之后才检查长度,因此出现“in”TypeError: var length = "length"in obj && obj.length
  • 是的,这就是为什么我建议将Object(obj) 作为in 表达式中的补丁。但显然你不能修补 jQuery(为什么?)。所以这是你能得到的最接近的,IMO。
  • XenForo 依赖于特定的 jQuery。看起来后来的 jQuery 版本添加了一个修复程序来解决这个问题( var length = !!obj && "length" in obj && obj.length )。由于 isArraylike 无法从外部访问,因此最好的 monkeypatch 可能最终成为替换 $.each ,其中包含更高(固定)版本的 isArraylike。
  • 我认为你可以只包含一个修补过的 jQuery,生成的 jQuery 对象只会覆盖 XenForo 包含的那个。只要在 XenForo 之后包含它,应该没问题。就我个人而言,我认为在代码中包含$.each 的修补实现是一个坏主意,这将调用isArrayLike 的更正版本,因为您还需要编写$.each 的其他逻辑。我真的认为最好用修改后的参数(使用Object)调用原始$.each,就像我在回答中建议的那样。
猜你喜欢
  • 1970-01-01
  • 2011-10-01
  • 2014-11-26
  • 1970-01-01
  • 2011-04-24
  • 1970-01-01
  • 2018-12-31
  • 2021-07-15
  • 2023-04-01
相关资源
最近更新 更多