如何填充元素的方法?

How to polyfill element's methods?

很多时候我发现我需要的方法在浏览器中并不普遍。我知道我不需要 polyfill 每次都解决这个问题,但我认为它们很有用,我想知道实现它们的步骤。

在这种情况下,我想填充 element.closest() 方法,但这只是一个示例。请注意,我的问题不是如何特别填充该方法,而是如何将该方法添加到 querySelector 中的每个新元素。

显然第一步是寻求支持:

if(!document.querySelector("body").closest){
  //Now that we know the method is not available,
  //we should modify the global methods of every new selection
  //so that it includes the new method.
}
function closest(property, value){
  while (x = x.parentElement) { 
    if (x[property] == value) return x;
  }
  return null;
}

我的问题是关于如何将其连接到块。你能帮帮我吗?

JavaScript有所谓"prototypal inheritance model".

您可以将 closest 方法添加到 Element 对象,如果它本身没有。

if (typeof(Element.prototype.closest == 'undefined')) {
  Element.prototype.closest = function(property, value) {
    var x = this;
    while (x = x.parentElement) { 
      if (x[property] == value) {
        return this;
      }
    }
    return null;
  }
}

你最接近的方法的用法是:

document.querySelector('#some-id').closest('href', 'http://google.com');

您可以使用 Element 来处理 Document 元素,例如 HTMLElementSVGElementHTMLElement 更具体。

UPD

The following interfaces all inherit from Node its methods and properties: Document, Element, CharacterData (which Text, Comment, and CDATASection inherit), ProcessingInstruction, DocumentFragment, DocumentType, Notation, Entity, EntityReference

https://developer.mozilla.org/en-US/docs/Web/API/Node

The Element interface represents an object of a Document. This interface describes methods and properties common to all kinds of elements. Specific behaviors are described in interfaces which inherit from Element but add additional functionality. For example, the HTMLElement interface is the base interface for HTML elements, while the SVGElement interface is the basis for all SVG elements.

https://developer.mozilla.org/en-US/docs/Web/API/Element

The HTMLElement interface represents any HTML element. Some elements directly implement this interface, others implement it via an interface that inherits it.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement

UPD2

您的 closest 代码不正确。我修好了。

您可以尝试完整的代码段。

if (typeof(Element.prototype.closest == 'undefined')) {
  Element.prototype.closest = function(property, value) {
    var x = this;
    while (x = x.parentElement) { 
      if (x[property] == value) {
        return this;
      }
    }
    return null;
  }
}


document.addEventListener("DOMContentLoaded", function(event) { 
  var a = document.querySelector('#my-image').closest('href', 'http://google.com/');
  console.log(a);
  alert(a);
});
<a href="http://google.com/"><img src="http://placehold.it/350x150" id="my-image" width="350" height="150"></a>

好的,你的 polyfill 函数已经准备好了。现在,你需要将它注入到节点对象中。

Node.prototype.closest = closest;

检查它是否正常工作:

if (typeof Node.prototype.closest == "undefined") {
  Node.prototype.closest = function () {
    console.log("Hi");
  }
}

如果你想对元素执行此操作,你需要使用 HTMLElement 对象:

if (typeof HTMLElement.prototype.closest == "undefined") {
  HTMLElement.prototype.closest = function () {
    console.log("Hi");
  }
}

那么您可以拨打:

document.closest();
a = document.querySelector("#one-element-with-id");
a.closest();