Ignoring the fact that this is implemented by many frameworks..
What is the best way to prototype for multiple object types.
For example, Should I write:
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);
}
};
or
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(eventTyp开发者_运维知识库e, fn, false);
}
}
}
Big red flag: never extend Object.prototype
! It breaks for (x in y)
(or at least people's expectations of how it works).
In the general case, however, it's better to extend the individual types' prototypes rather than try to find a common base and perform reflection checks. There are two basic reasons to do this.
First, JavaScript is a dynamically typed language, so you should generally prefer duck typing and basic inheritance over instanceof
and reflection. In many cases, there is a small performance benefit, but mainly this is so you don't spend time fighting the language.
Second, this type of method switching implies connections between the switched methods which do not necessarily exist. In your sample code, this can be seen in the NodeList
version. Conceptually, a list shouldn't be binding anything; if it has a bind
method, it should simply translate into calling the bind
method on each of its elements. This ensures that if any extra steps need added to binding in the future (say, workarounds for old, non-DOM-conforming browsers…), you only need to do so in one place.
But looking at it in terms of type switching in the "same function" gives the false impression that both Element.bind
and NodeList.bind
should work the same way — by calling addEventListener
. Here's how I'd implement it:
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);
}
};
精彩评论