adding custom functions into Array.prototype
I was working on an AJAX-enabled asp.net application. I've just added some methods to Array.prototype like
Array.prototype.doSomething = function(){
...
}
This solution worked for me, being possible reuse code in a 'pretty' way.
But when I've tested it working with the entire page, I had problems.. We had some custom ajax extenders, and they started to behave as the unexpected: some controls displayed 'undefined' around its content or value.
What could be the cause for that? Am I missing something about modifing the prototype of standart objects?
Note: I'm pretty sure that the error begins when I modify the prototype for Array. It should be only compatible with IE.
Modifying the built-in object prototypes can be a bad idea in general, because it always has the potential to clash with other code on the same page.
In the case of the Array object prototype, it is an especially bad idea, because it has the potential to interfere with any piece of code that iterates over the members of any array, for instance with for .. in
.
To illustrate using an example (borrowed from here):
Array.prototype.foo = 1;
// somewhere deep in other javascript code...
var a = [1,2,3,4,5];
for (x in a){
// Now foo is a part of EVERY array and
// will show up here as a value of 'x'
}
It would be better for you to create your own type of object constructor complete with doSomething function, rather than extending the built-in Array.
Edit: to repeat what I put in a comment:
The inverse is true - you should avoid for..in in case some n00b has modified the Array prototype, and you should avoid modifying the Array prototype in case some n00b has used for..in on an array. ;)
Also, there now exists Object.defineProperty
as a general way of extending object prototypes without the new properties being enumerable, though I still wouldn't use this as justification for extending the built-in types, because even besides for..in
there is still the potential for other conflicts with other scripts. Consider someone forking your code and then putting both versions on the same page - will your custom enhancement to the Array object still work as you expect?
尽管与其他位碰撞的可能性代码重写原型上的函数仍然是一个风险,如果你想用现代版本的JavaScript来做到这一点,你可以使用Object.defineProperty方法,关闭可枚举位,例如
// functional sort
Object.defineProperty(Array.prototype, 'sortf', {
enumerable: false,
value: function(compare) { return [].concat(this).sort(compare); }
});
There is a caution! Maybe you did that: fiddle demo
Let us say an array and a method foo which return first element:
var myArray = ["apple","ball","cat"];
foo(myArray) // <- 'apple'
function foo(array){
return array[0]
}
The above is okay because the functions are uplifted to the top during interpretation time.
But, this DOES NOT work: (Because the prototype is not definned)
myArray.foo() // <- 'undefined function foo'
Array.prototype.foo = function(){
return this[0]
}
For this to work, simply define prototypes at the top:
Array.prototype.foo = function(){
return this[0]
}
myArray.foo() // <- 'apple'
And YES! You can override prototypes!!! It is ALLOWED. You can even define your own own add
method for Arrays.