5

我想以这样的方式连接到 document.createElement 函数,每次创建 div 元素时,我的钩子都会将“foo”属性附加到 div。这是我目前拥有的:

<script>
    window.onload = function () {
        console.log("document loaded");
        document.prototype.createElement = function (input) {
            var div = document.createElement(input);
            console.log("createElement hook attached!");
            if (input == "div")div.foo = "bar";
            return div;
        }

        document.body.addEventListener('onready', function () {
            var div = document.createElement("div");
            console.log(div.foo);
        });

    }
</script>

当我在 Chrome 中运行它时,我收到一条错误消息

Uncaught TypeError: Cannot set property 'createElement' of undefined test.html:4 window.onload

(我更改了上面错误消息中的行号以匹配我的代码)

我在这里错了什么?我怎样才能解决这个问题?

4

2 回答 2

11
  • document没有.prototype, 因为它是实例对象而不是构造函数
  • 你在你的新函数中调用 new document.createElement,它最终会递归。您需要在某处存储对旧引用的引用,然后调用它。
  • 您正在设置属性而不是属性
  • 这是非常脆弱的事情,不能保证有效。它似乎在 chrome 和 firefox 中工作,但在旧 IE 中不起作用

尝试这个

document.createElement = function(create) {
    return function() {
        var ret = create.apply(this, arguments);
        if (ret.tagName.toLowerCase() === "div") {
            ret.setAttribute("foo", "bar");
        }
        return ret;
    };
}(document.createElement)

http://jsfiddle.net/NgxaK/2/

于 2012-07-30T18:57:56.060 回答
1

我建议不要覆盖现有函数,因为它们将来可能会变为只读。我建议对 DOM 进行后处理(快速遍历 div 比拦截每个元素的创建要快)和/或修改插入 div 的代码以添加您的属性。或者,如果您真的想修改创建的节点,更好的方法是 Mutation Observers (HTML5):

http://updates.html5rocks.com/2012/02/Detect-DOM-changes-with-Mutation-Observers

这比使用 HTML4 中已弃用的突变事件要好得多,并且覆盖全局变量通常被认为是一种不好的做法,除非您正在创建 shim 或 polyfill。

于 2012-07-30T19:10:46.657 回答