NodeList原型中的对象

时间:2012-06-05 12:03:24

标签: javascript prototype

一些原生javascript对象的原型可以扩展为包含新功能(例如NodeList.prototype.forEachNodeList.prototype.addEventListener),我使用它来允许与NodeList进行数组和类似元素的交互。到目前为止一切都那么好,但我应该如何向原型添加一个对象,而原型又有自己的功能(允许NodeListVar.classList.remove("class"))。通过执行以下操作,我已经能够NodeListVar.classList().remove("class")

NodeList.prototype.classList = function(){
    var _this = this;
    return {
        remove: function(class){
            _this.forEach(function(){
                this.classList.remove(class);
            });
        }
    }   
};

但是我更希望语法与普通element相同,因此更像是:

NodeList.prototype.classList = {
    remove: function(class){
        //where *this* would be the nodeList and *not* the DOMWindow
        this.forEach(function(){
            this.classList.remove(class);
        });
    }
};

它可能并不难,但我已经无休止地搜索谷歌,已经查看了无数问题,找不到任何有用的东西。

2 个答案:

答案 0 :(得分:2)

首先阅读:What’s wrong with extending the DOM

您无法在原型上设置对象。所有被调用的函数都将在该静态原型对象的上下文中执行,而不是NodeList本身。原型上的对象没有引用当前的NodeList。

在普通Element上,每个元素都有自己的classList属性,DOMTokenList绑定了元素。您将需要执行相同的操作:为每个NodeList提供自己的classLists实例。正如您在不可用的构造函数中无法做到的那样,您必须使用getter,如前所述。

我认为您不应该尝试在NodeLists上使用与Elements相同的语法,因为它们非常不同。但是如果你想摆脱这些括号,可以安装native getter function

function ClassLists(nl) {
    ... // nl references the NodeList we're bound to
}
ClassLists.prototype = ...;

Object.defineProperty(NodeList.prototype, "classLists", {
    get: function() {
        return this.classLists = new ClassLists(this);
    }
});

答案 1 :(得分:0)

为了补充@ Bergi的答案,这是一个跨浏览器的解决方案:

function ClassList() {
    this.nodeList;
}

ClassList.prototype = {
    constructor: ClassList,

    remove: function() {
        console.log( this );
    }
};

NodeList.prototype.classList = new ClassList();

nl.classList.remove(); // ClassList object with the `nodeList` property.

它不能与同一个API一起使用,因为它不使用defineProperty,但它是跨浏览器。 defineProperty仅在IE9中可用,并且在IE7中不可调。

相关问题