我必须为无法修改的外部脚本提供画布。不幸的是,我稍后必须更换画布,因此我创建了一个简单的可变代理。但是,外部脚本尝试以我的代理对象作为第二个参数执行insertBefore,但它以某种方式失败了。

重现问题(摆脱了可变性以简化一点):

var canvas = new Proxy(document.getElementById("canvas"), {
    get: function get(target, property, receiver) {
      let originalProperty = target[property]
      return typeof originalProperty === "function"
        ? originalProperty.bind(target)
        : originalProperty
    },
    set: function(target, property, value, receiver) {
      target[property] = value
    }
  })

canvas.parentElement.insertBefore(document.createElement('div'), canvas)


结果:

Uncaught TypeError: Failed to execute 'insertBefore' on 'Node': parameter 2 is not of type 'Node'.


有趣的是:canvas instanceof Node返回truetypeof canvas返回"object",但typeof document.getElementById("canvas")也返回。

最佳答案

解决方案涉及重载Node.prototype.insertBefore并使用How to get the target of a JavaScript Proxy?中的方法

在代理处理程序中,getter为属性PROXY_NODE添加了一个条件以返回原始目标节点。

然后在insertBefore重载中,检查该属性是否为真,并更改第一个参数为



const PROXY_NODE = Symbol('PROXY_NODE');

// Overload Node.prototype.insertBefore
const oldInsertBefore = Node.prototype.insertBefore;

Node.prototype.insertBefore = function(...args) {
  if (args[0][PROXY_NODE]) {
    args[0] = args[0][PROXY_NODE];
    console.log(args[0]);
  }
  oldInsertBefore.apply(this, args)
}

// proxy handler
const handler = {
  get: (target, property, receiver) => {
    if (property === PROXY_NODE) {
      return target
    }
    return Reflect.get(target, property, receiver)
  },
  set: function(target, property, value, receiver) {
    target[property] = value
  }
}

// Create proxy node
const proxyNode = new Proxy(document.createElement("div"), handler);
// proxy setter is working
proxyNode.textContent = 'Proxy Content';

// insert proxy node
var parentDiv = document.getElementById("parentElement");
var childDiv = document.getElementById("childElement");
parentDiv.insertBefore(proxyNode, childDiv );

<div id="parentElement">
  <div id="childElement">Child</div>
</div>

关于javascript - insertBefore代理元素:参数2的类型不是“节点”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57240828/

10-13 06:59