Javascript: What Dangers Are in Extending Array.Prototype

JavaScript: What dangers are in extending Array.prototype?

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 extending Array.prototype or other native prototypes might come down to one of these:

  1. for..in might not work properly
  2. Someone else might also want to extend Array with the same function name
  3. It might not work properly in every browser, even with the shim.

Here are my responses:

  1. You don't need to use for..in on Array's usually. If you do you can use hasOwnProperty to make sure it's legit.
  2. Only extend natives when you know you're the only one doing it OR when it's standard stuff like Array.prototype.filter.
  3. This is annoying and has bit me. Old IE sometimes has problems with adding this kind of functionality. You'll just have to see if it works in a case by case basis. For me the problem I had was adding Object.keys to IE7. It seemed to stop working under certain circumstances. Your mileage may vary.

Check out these references:

  • http://perfectionkills.com/extending-native-builtins/
  • http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542
  • https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
  • https://github.com/kriskowal/es5-shim

Good luck!

Extending Array.prototype crashes

When you push the value to same array during loop, you end up in infinite loop, create a temp array push value to it, in the end add it to this

const a = [1, 2, 3, 4, 5];
//this is the what I triedArray.prototype.multiply = function() { let newArr = [] for (const m of this) { newArr.push(m * m) } this.push(...newArr)}
a.multiply();console.log(a);

Extending JavaScript's built-in types - is it evil?

This is precisely the reason why you must try to pollute the global namespace as little as possible. The only way to completely avoid any sort of clashes is by defining everything within an IIFE:

(function () {
let Collection = ...
})();

If and only if you need to define global objects, for instance because you're a library and you want to be used by 3rd parties, you should define a name which is extremely unlikely to clash, for instance because it's your company name:

new google.maps.Map(...)

Any time you define a global object, which includes new methods on existing types, you're running the risk of some other library or some future ECMAScript standard trying to co-opt the name sometime in the future.

Extending Array prototype in JavaScript

Generally speaking you should avoid extending base objects because it may clash with other extensions of that object. Ideally extending Array and then modifying THAT is the safest way to do things as it is guaranteed to not clash with other developers who might try to do the same thing (even though they shouldn't).

Basically, avoid extending base objects when possible because it can get you into trouble for very little real benefit compared to extending the array object.

Why is extending native objects a bad practice?

When you extend an object, you change its behaviour.

Changing the behaviour of an object that will only be used by your own code is fine. But when you change the behaviour of something that is also used by other code there is a risk that you will break that other code.

When method are added to the object and array classes in javascript, the risk of breaking something is very high - due to how javascript works. Long years of experience have taught me that this kind of stuff causes all kinds of terrible bugs in javascript.

If you need custom behaviour, it is far better to define your own class (perhaps a subclass) instead of changing a native one. That way you will not break anything at all.

The ability to change how a class works without subclassing is an important feature of any good programming language, but it is one that must be used rarely and with caution.

How to properly extend Array prototype in Typescript 4.0.3?

Array is defined as an interface not a type. Interfaces in typescript are open ended and can be added to by multiple declarations. Types do not share the same feature.

export{}
declare global {
interface Array<T> {
intersperse(mkT: (ix: number) => T): T[];
}
}

if (!Array.prototype.intersperse) {
Array.prototype.intersperse = function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
};
}

Playground Link

As T.J. Crowder mentioned you might consider using Object.defineProperty to ensure the property is not enumerable:

export {}
declare global {
interface Array<T> {
intersperse(mkT: (ix: number) => T): T[];
}
}

if (!Array.prototype.intersperse) {
Object.defineProperty(Array.prototype, 'intersperse', {
enumerable: false,
writable: false,
configurable: false,
value: function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
}
});
}

Playground Link

What's wrong if we extend prototypes in Node.js of any object?

You are not extending any prototype in the example you provided above. The prototype property only exists on functions - AryUser is an array. The above code will throw a ReferenceError.

You may wish to learn how prototypal inheritance works in JavaScript. Read the following answer: https://stackoverflow.com/a/8096017/783743

That being said it's a bad practice to extend prototypes of native functions like Function, Object and Array. This is because you might overwrite someone else's function, possibly breaking their code.

Extending native function prototypes is only recommended for monkey patching. Read the following article to understand the pros and cons of extending native function prototypes.



Related Topics



Leave a reply



Submit