2012-07-30 67 views
2

我想以这种方式挂钩到document.createElement函数上,每次创建div元素时,我的挂钩都会将“foo”属性附加到div。这是我目前:使用函数原型挂接document.createElement

<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 

(我改变错误消息的行号以上,以配合我的代码)

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

+0

扩展'document'的'prototype'!哇,祝你好运.. – 2012-07-30 18:56:29

+1

与DOM对象混合是一个非常痛苦的事情跨浏览器做。 Prototype JS库没有成功的原因之一。您可能希望围绕您希望扩展的任何位置创建一个包装对象。 http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – 2012-07-30 19:15:08

+0

不要手动构建dom,尤其是没有库。除非这是个人学习项目,否则使用模板引擎和库来执行DOM操作,或者您正在寻求维护和便携性的噩梦。截取createElement是不必要的,并且这在将来可能不会总是可能的。 – 2012-07-30 19:22:25

回答

5
  • document没有.prototype,因为它是一个实例对象,而不是一个构造函数
  • 你在你的新函数调用新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/

+0

这不会修改页面上已有的div。而且,apply也是不必要的,并且比直接调用原始的'createElement'要慢很多。 – 2012-07-30 19:19:08

+0

我不认为他希望它修改已经存在的div。至于'.apply',我只是保证在传递给新函数时参数完全传递给'document.createElement'。我怀疑它比'.call'慢得多。 – Esailija 2012-07-30 19:20:41

+0

'调用'也很慢,比直接调用慢10倍左右。 “应用”通常是3-5倍慢,甚至。没有快速的方法来包装一个受其调用范围保护的全局,这就是为什么我没有提出这样的建议。 – 2012-07-30 19:28:45

1

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

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

这比使用已在HTML4被弃用的突变事件更好的选择,覆盖全局通常被认为是不好的做法,除非你创建一个垫片或一个polyfill。