拥有 JS API return polyfilled DOM 节点

Have JS APIs return a polyfilled DOM node

我正在使用 HTML 中的 <data> 元素,它具有不错的支持,但不足以满足我的目的。 HTMLDataElement 中的额外功能是 value 的 getter,returns 相应的属性。

当然这实现起来很简单,只需使用以下代码(当然是在特征检测之后)

class HTMLDataElement extends HTMLElement {
    constructor() {
        super();
    }

    get value() {
        return this.getAttribute(`value`);
    }
}

效果很好。只有一个问题:当使用 getElementByIdquerySelector 等原生 API 时,返回的 Node 不是实例 HTMLDataElement。如果可能的话,我怎样才能做到这一点?

明确地说,我希望能够做到 document.querySelector('foo').value,不管有没有浏览器支持 <data>.

,它的行为都是一样的

(我很清楚我可以只使用 .getAttribute('value') 而不是 .value。重点是我不想。)

在 Twitter 上联系 Jonathan Neal* 后,他提供了一个很好的例子来说明如何做到这一点。

if (!this.HTMLDataElement) {
    this.HTMLDataElement = this.HTMLUnknownElement;

    const valueDescriptor = Object.getOwnPropertyDescriptor(HTMLDataElement.prototype, 'value');

    Object.defineProperty(
        HTMLDataElement.prototype,
        'value',
        valueDescriptor || {
            get() {
                return 'DATA' === this.nodeName && this.getAttribute('value');
            }
        }
    );
}

console.log('data:', document.querySelector('data').value);

console.log('xdata:', document.querySelector('xdata').value);
<data value="this should work">
<xdata value="this should not work">

* 对于不熟悉的人,Jonathan Neal 是 PostCSS 插件的主要贡献者,他自己创建了许多 JavaScript polyfill。