Quiz

Why is extending built-in JavaScript objects not a good idea?

Topics
JavaScriptOOP
Edit on GitHub

TL;DR

Extending a built-in/native JavaScript object means adding properties/functions to its prototype. While this may seem like a good idea at first, it is dangerous in practice. Imagine your code uses a few libraries that both extend the Array.prototype by adding the same contains method, the implementations will overwrite each other and your code will have unpredictable behavior if these two methods do not work the same way.

The only time you may want to extend a native object is when you want to create a polyfill, essentially providing your own implementation for a method that is part of the JavaScript specification but might not exist in the user's browser due to it being an older browser.


Extending JavaScript

In JavaScript it's very easy to extend a built-in/native object. You can simply extend a built-in object by adding properties and functions to its prototype.

String.prototype.reverseString = function () {
return this.split('').reverse().join('');
};
console.log('hello world'.reverseString()); // Outputs 'dlrow olleh'
// Instead of extending the built-in object, write a pure utility function to do it.
function reverseString(str) {
return str.split('').reverse().join('');
}
console.log(reverseString('hello world')); // Outputs 'dlrow olleh'

Disadvantages

Extending built-in JavaScript objects is essentially modifying the global scope and it's not a good idea because:

  1. Future-proofing: If a browser decides to implement its own version of a method, your custom extension might get overridden silently, leading to unexpected behavior or conflicts.
  2. Collisions: Adding custom methods to built-in objects can lead to collisions with future browser implementations or other libraries, causing unexpected behavior or errors.
  3. Maintenance and debugging: When extending built-in objects, it can be difficult for other developers to understand the changes made, making maintenance and debugging more challenging.
  4. Performance: Extending built-in objects can potentially impact performance, especially if the extensions are not optimized for the specific use case.
  5. Security: In some cases, extending built-in objects can introduce security vulnerabilities if not done correctly, such as adding enumerable properties that can be exploited by malicious code.
  6. Compatibility: Custom extensions to built-in objects may not be compatible with all browsers or environments, leading to issues with cross-browser compatibility.
  7. Namespace clashes: Extending built-in objects can lead to namespace clashes if multiple libraries or scripts extend the same object in different ways, causing conflicts and unexpected behavior.

We dive deeper into why it is a bad idea to modify the global scope.

It is not recommended to extend built-in objects due to these potential issues and instead suggest using composition or creating custom classes and utility functions to achieve the desired functionality.

Alternatives to extending built-in objects

Instead of extending built-in objects, do the following instead:

  1. Create custom utility functions: For simple tasks, creating small utility functions specific to your needs can be a cleaner and more maintainable solution.
  2. Use libraries and frameworks: Many libraries and frameworks provide their own helper methods and extensions, eliminating the need to modify built-in objects directly.

Polyfilling as a valid reason

One valid reason to extend built-in objects is to implement polyfills for the latest ECMAScript standard and proposals. core-js is a popular library that is present on most popular websites. It not only polyfills missing features but also fixes incorrect or non-compliant implementations of JavaScript features in various browsers and runtimes.

import 'core-js/actual/array/flat-map'; // With this, Array.prototype.flatMap is available to be used.
[1, 2].flatMap((it) => [it, it]); // => [1, 1, 2, 2]

Further reading

Edit on GitHub