hook document.createElement脚本来更改src

时间:2018-06-08 21:26:47

标签: javascript dom

我正在尝试挂钩document.createElement来更改每个作业的src属性值。

以下是我正在做的事情:

var original = document.createElement;
    document.createElement = function (tag) {
      var element = original.call(document, tag);
      if (tag.toLowerCase() === 'script') {
        Object.defineProperty(element.__proto__, 'src', {
          set: function(newValue) {
            element['src'] = 'test';
          }
        });
      }
      return element;
    };

问题是element['src'] = 'test';再次调用setter并再次导致堆栈溢出。 我尝试了不同的方法,我将局部变量保存在外部,并将其值设置为newValue,并将getter添加到返回它的src属性中。 这种方法的问题在于,如果稍后将脚本元素附加到dom,则会添加一个不具有src属性的脚本标记,就像append方法试图获取src属性一样然后以不同的方式正常访问它,这样就不会调用getter,所以我留下了一个空的脚本标记。

在这种情况下,我可以做些什么,如何做到这一点,以便我可以用另一个值'替换'用于脚本的src属性的值?

编辑: 这是我最终得到的钩子:

    Object.defineProperty(HTMLScriptElement.prototype, 'src', {
  set: function(newValue) {
    const r = /(?:[^:]+:)?\\/\\//;
    if (r.test(newValue)) {
      this.setAttribute("src", 'http://localhost:8080/v1/proxy?url=' + (newValue.startsWith('http') ? encodeURIComponent(newValue) : encodeURIComponent('http:' + newValue)));
    } else {
      this.setAttribute("src", 'http://localhost:8080/v1/proxy?url=' + encodeURIComponent(absolute('${originalHost}', newValue)));
    }
  }
});

我意识到我需要涵盖所有可能的更改方式src script元素的属性,包括setAttribute('src', '...') 如果我要挂钩setAttribute,我会导致堆栈溢出,因为我已经挂钩了src属性setter并在其中使用了setAttribute。 如何才能实现挂钩setAttribute以便完全控制src值而不会导致堆栈溢出?

1 个答案:

答案 0 :(得分:1)

混淆你没有创建的方法和原型是非常糟糕的做法,但无论如何这里可能是你的解决方案。

只需将“element['src'] = 'test';”替换为“element.setAttribute('src', 'test');”即可。这样你就可以避免使用该属性。 setAttribute方法直接与元素的属性交互,而不是通过浏览器的属性getter。