一些原生javascript对象的原型可以扩展为包含新功能(例如NodeList.prototype.forEach
或NodeList.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);
});
}
};
它可能并不难,但我已经无休止地搜索谷歌,已经查看了无数问题,找不到任何有用的东西。
答案 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中不可调。