覆盖(monkeypatch)querySelector,然后在浏览器JS中恢复原始功能

问题描述 投票:0回答:1

我有一个本地测试环境,我想在其中临时覆盖querySelector。我知道猴子补丁是不好的做法,但在这种情况下,此代码将仅在开发人员本地使用。我写了这个片段(覆盖 querySelector 以使用选择器中名为 addonID 的另一个子字符串来获取所有选择器):

  function maybeOverrideForTestStart(partialIDOfWidget, fullIDOfWidget) {
    if(!isLocal) return;
    const addonID = fullIDOfWidget.replace(partialIDOfWidget, "");
    Element.prototype.querySelectorTemp = Element.prototype.querySelector.bind(Element);
    
    Element.prototype.querySelector = function(selector) {
      const element = this.querySelectorTemp(selector);
      if (element) return element;
      if (addonID) {
        return this.querySelectorTemp(selector + addonID) || null;
      }
    };

  }
  function maybeOverrideForTestEnd() {
    if(!isLocal) return;
    Element.prototype.querySelector = Element.querySelectorTemp;
  }

我在测试开始时调用

maybeOverrideForTestStart
,在测试结束时调用
maybeOverrideForTestEnd
。但这不起作用,而且我不确定我错过了什么。我得到的是
someElement.querySelector is not a function
"Uncaught TypeError: Illegal invocation"

注意 - 我也无法理解这是否也覆盖了 document.querySelector 和 document.body.querySelector 或者只是 someElement.querySelector。

感谢帮助,谢谢。

javascript monkeypatching queryselector
1个回答
0
投票

我不确定您是否需要

.bind()
该函数,但您可以在常量中保留对原始函数的引用,例如

const querySelector = Element.prototype.querySelector;

function maybeOverrideForTestStart(partialIDOfWidget, fullIDOfWidget) {
  // ....

  Element.prototype.querySelector = function (selector) {
    const element = querySelector(selector);
    if (element) return element;
    if (addonID) {
      return querySelectorTemp(selector + addonID) || null;
    }
  };
}

function maybeOverrideForTestEnd() {
  // ...
  Element.prototype.querySelector = querySelector;
}
© www.soinside.com 2019 - 2024. All rights reserved.