忽略这是由 许多 框架实现的事实..
为多种对象类型制作原型的最佳方法是什么。
例如,我应该写:
Element.prototype.bind = function(eventType, fn) {
this.addEventListener(eventType, fn, false);
};
NodeList.prototype.bind = function(eventType, fn) {
for (var i = 0, l = this.length; i < l; i++) {
this[i].addEventListener(eventType, fn, false);
}
};
或
Object.prototype.bind = function(eventType, fn) {
if (this instanceof Element) {
this.addEventListener(eventType, fn, false);
} else if (this instanceof NodeList) {
for (var i = 0, l = this.length; i < l; i++) {
this[i].addEventListener(eventType, fn, false);
}
}
}
答案 0 :(得分:3)
大红旗:从不延长Object.prototype
!它会打破for (x in y)
(或者至少是人们对它如何运作的期望)。
但是,在一般情况下,最好扩展单个类型的原型,而不是尝试查找公共基础并执行反射检查。这样做有两个基本原因。
首先,JavaScript是一种动态类型语言,因此您通常应该优先选择鸭子类型和基本继承而不是instanceof
和反射。在许多情况下,有一个小的性能优势,但主要是因为你不花时间与语言作斗争。
其次,这种类型的方法切换意味着切换方法之间的连接不一定存在。在您的示例代码中,可以在NodeList
版本中看到。从概念上讲,列表不应该绑定任何东西;如果它有bind
方法,它应该简单地转换为在每个元素上调用bind
方法。这确保了如果将来需要为绑定添加任何额外步骤(例如,旧的,不符合DOM的浏览器的变通方法......),您只需要在一个地方执行此操作。
但是,根据“相同功能”中的类型切换来看待它会给人以错误的印象:Element.bind
和NodeList.bind
应该以相同的方式工作 - 通过调用addEventListener
。以下是我实现它的方法:
Element.prototype.bind = function(eventType, fn) {
this.addEventListener(eventType, fn, false);
};
NodeList.prototype.bind = function(eventType, fn) {
for (var i = 0, l = this.length; i < l; i++) {
this[i].bind(eventType, fn);
}
};