Google JavaScript Style Guide advises against extending the Array.prototype
.
However, I used Array.prototype.filter = Array.prototype.filter || function(...) {...}
as a way to have it (and similar methods) in browsers where they do not exist. MDN actually provides similar example.
I am aware about Object.prototype
issues, but Array
is not a hash table.
What issues may arise while extending Array.prototype
that made Google advise against it?
I believe this question deserves an updated ES6 answer.
ES5
First of all, as many people have already stated. Extending the native prototypes to shim or polyfill new standards or fix bugs is standard practice and not harmful. For example if a browser doesn't support the .filter method
if (!Array.prototype.filter)
you are free to add this functionality on your own. In-fact, the language is designed to do exactly this to manage backwards compatibility.Now, you'd be forgving for thinking that since JavaScript object use prototypal inheritance, extending a native object like
Array.prototype
without interfering should be easy, but up until ES6 it's not been feasible.Unlike objects for example, you had to rely and modifying the
Array.prototype
to add your own custom methods. As others have pointed out, this is bad because it pollutes the Global namespace, can interfere with other code in an unexpected way, has potential security issues, is a cardinal sin etc.In ES5 you can try hacking this but the implementations aren't really practically useful. For more in depth information, I recommend you check out this very informative post: http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
You can add a method to an array, or even an array constructor but you run into issues trying to work with the native array methods that rely on the length property. Worst of all, these methods are going to return a native
Array.prototype
and not your shiny new sub-class array, ie:subClassArray.slice(0) instanceof subClassArray === false
.ES6
However, now with ES6 you can subclass builtins using
class
combined withextends Array
that overcomes all these issues. It leaves theArray.prototype
intact, creates a new sub-class and the array methods it inherits will be of the same sub-class! https://hacks.mozilla.org/2015/08/es6-in-depth-subclassing/See the fiddle below for a demonstration: https://jsfiddle.net/dmq8o0q4/1/
The function you are overriding could be used by the internal javascript calls and that could lead to unexpected results. Thats one of the reasons for the guideline
For example I overrode indexOf function of array and it messed up accessing array using [].
Most people missed the point on this one. Polyfilling or shimming standard functionality like
Array.prototype.filter
so that it works in older browsers is a good idea in my opinion. Don't listen to the haters. Mozilla even shows you how to do this on the MDN. Usually the advice for not extendingArray.prototype
or other native prototypes might come down to one of these:for..in
might not work properlyHere are my responses:
for..in
on Array's usually. If you do you can usehasOwnProperty
to make sure it's legit.Array.prototype.filter
.Object.keys
to IE7. It seemed to stop working under certain circumstances. Your mileage may vary.Check out these references:
Good luck!
Extending
Array.prototype
in your own application code is safe (unless you usefor .. in
on arrays, in which case you need to pay for that and have fun refactoring them).Extending native host objects in libraries you intend others to use is not cool. You have no right to corrupt the environment of other people in your own library.
Either do this behind an optional method like
lib.extendNatives()
or have[].filter
as a requirement.Extending Natives and Host Objects