如何将自己的方法添加到HTMLElement对象?

31
例如,对于this.parentNode,我想只写this.p,或者使用document.g('someid')代替document.getElementById('someid')。当然,这只是简单的例子,我想知道正确的做法。 (我知道可以使用jQuery或Prototype,但我想学习JS中真正的方法)
5个回答

43

虽然在很多浏览器中,你可以HTMLElement上进行原型开发,但Internet Explorer(6,7,8)不支持。据我所知,IE9支持此功能(尽管我没有测试)。

对于支持它的浏览器,你可以这样做:

HTMLElement.prototype.doHello = function(thing){
  console.log(this + ' says: ' + thing)
}

document.body.doHello('hello')


3
@Flash Thunder - 我在回答中已经表明了... IE6、7、8 明确被从“支持”列表中剔除。 - scunliffe
1
是的,但您可以简单地使用“Object”代替“HTMLElement”。 - Flash Thunder
但是 OP 想要在 HTML 元素上绑定方法 - 使用外部对象会破坏这个目的...此时像 jQuery 这样的东西会更好(因为他们已经解决了这个问题以及更多问题) - scunliffe
2
但是使用 HTMLElement.prototype.… 时,您无法像使用 String.prototype.… 一样使用 thisself 来定位元素 :( - iiic

14

我强烈建议不要尝试这样做,原因如下:

  • 浏览器兼容性。虽然在几个浏览器中可能是可行的,但在IE <= 8中不可能。
  • DOM元素是宿主对象。宿主对象(即由环境提供的不是本机JavaScript对象)没有义务遵守与本机JavaScript对象和其他指定DOM行为不同的规则,基本上可以按照其意愿进行操作。所以,即使一些浏览器提供了HTMLElement原型并允许您增加它,也不能保证它将按预期工作。
  • 与页面中其他代码的兼容性。如果页面中的任何其他代码(例如Prototype)干扰了HTMLElement原型,您就会面临命名冲突和难以检测的错误。

相反,我建议创建包装器对象来包装DOM节点,就像jQuery、YUI和其他库一样。

Kangax撰写了一篇有关DOM可扩展性的好文章,涵盖了所有这些点以及更多内容。


你确定要使用jQuery吗?据我所知,当使用.data()时,jQuery会扩展DOM元素和其他元素。- https://github.com/jquery/jquery/blob/master/src/data/Data.js - JojOatXGME
2
@JojOatXGME:是的,在data()的特定情况下,jQuery确实在DOM元素上存储了一个“expando”属性(但不是方法)。我怀疑它可能还使用expandos来跟踪事件侦听器和可能的其他内容。然而,总体上的观点是:jQuery的API通过包装器对象提供扩展的DOM功能,而不是通过扩展DOM本身来实现。它对DOM的扩展仅在内部使用。 - Tim Down

3

3

这篇来自perfectionkills.com的文章可能会让你了解它是如何完成的,以及为什么你不应该这样做。

(顺便说一句,jQuery不扩展DOM元素。它们使用DOM包装器。)


2

如果您想包装像document这样的全局对象,那么这可能不是您要寻找的内容,但是您可以使用自定义元素[1][2]来创建类似于HTMLElement的节点,从而获得类似的效果。

  1. 创建自定义元素
  2. 向自定义元素类添加方法
  3. 您可以调用该方法
export class CustomElementInput extends HTMLElement {

  log(){
    alert("log")
  }

  // you can even overwrite methods like so
  remove(){
    alert("removing this node")
    super.remove()
  }
}

customElements.define("custom-element-input", CustomElementInput)

// somewhere else...
// in your HTML something like:
// <custom-element-input></custom-element-input> 

const el = document.querySelector("custom-element-input")
el.log() // creates alert()

2
这正是我在寻找的。在我看来,纯自定义元素被低估了。 - Llama D'Attore
2
@LlamaD'Attore 对吧?香草定制元素非常灵活、强大,是一种很好的方式来模块化与HTML相关的所有JavaScript代码。而且,无论有多少新的JS框架出现,它永远不会过时。 - Jose V
在我的经验中,它比任何框架都好100%,而且我用过Angular、React、Next、Vue和Svelte等等。 - undefined
1
@LlamaD'Attore 对吧?我了解到你可以使用Preact来创建Web组件,我可能会尝试一下。我的目标是使用服务器端HTML模板,并为动态部分添加一些Web组件,但只是少量使用。与SPA不同,它会消耗你应用程序中的所有内容。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接