quiz/js: avoid global scope pollution and extension of built-in js objects (#447)

This commit is contained in:
Vikas yadav 2024-06-05 06:05:24 +05:30 committed by GitHub
parent e025eb85b6
commit 342af3f00d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 128 additions and 0 deletions

View File

@ -2,6 +2,54 @@
title: Why is extending built-in JavaScript objects not a good idea?
---
## 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 break if the behavior of these two methods is not the same.
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.
---
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`.
```js
String.prototype.reverseString = function () {
return this.split('').reverse().join('');
};
console.log('hello world'.reverseString()); // Outputs 'dlrow olleh'
// instead of extending the built in object you can write a simple utility function to do it
function reverseString(str) {
return str.split('').reverse().join('');
}
console.log(reverseString('hello world')); // Outputs 'dlrow olleh'
```
### Disadvantages
It is not recommended to extend built-in objects. Extending built-in JavaScript objects can have several disadvantages:
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.
### Alternatives to extending built-in objects:
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.
## Summary
Many developers and experts recommend against extending 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.
## Further reading
- [JS: dont extend JS objects](https://lucybain.com/blog/2014/js-extending-built-in-objects/)
- [Extending built-in classes](https://javascript.info/extend-natives)

View File

@ -2,4 +2,84 @@
title: Why is it, in general, a good idea to leave the global scope of a website as-is and never touch it?
---
## TL;DR
JavaScript that is executed in the browser has access to the global scope, and if everyone uses the global namespace to define their variables, collisions will likely occur. Use the module pattern (IIFEs) to encapsulate your variables within a local namespace.
### Example
#### Using global scope
```js
let count = 0;
function incrementCount() {
count++;
console.log(count);
}
function decrementCount() {
count--;
console.log(count);
}
incrementCount(); // Output: 1
decrementCount(); // Output: 0
```
In this example, `count`, `incrementCount`, and `decrementCount` are all defined in the global scope. Any script on the page can access and modify these variables and functions.
#### Using IIFE (Immediately invoked function expression)
```js
(function () {
let count = 0;
window.incrementCount = function () {
count++;
console.log(count);
};
window.decrementCount = function () {
count--;
console.log(count);
};
})();
incrementCount(); // Output: 1
decrementCount(); // Output: 0
```
In this example, `count` is not accessible in the global scope. It can only be accessed and modified by the `incrementCount` and `decrementCount` functions. These functions are exposed to the global scope by attaching them to the `window` object, but they still have access to the `count` variable in their parent scope. This provides a way to encapsulate data and avoid polluting the global scope.
---
In JavaScript, it is very easy to define variables and functions in global scope. You can declare a variable globally by simply assigning a value to it outside of any function:
```js
var myGlobalVar = 'Hello World';
```
Global variables are accessible from anywhere in your JavaScript code. It's generally recommended to avoid using global variables whenever possible due to following reasons:
1. **Global Variables are Considered a "Bad Thing"**: Global variables are generally considered a bad practice in most programming languages, including JavaScript. They can lead to code that is harder to read, maintain, and debug.
2. **Unpredictable Behavior**: Global variables can be updated from any point in the program, making it difficult to predict their values. This can lead to unexpected behavior and side effects.
3. **Name Clashes**: Since there is only one global namespace, it is more likely to encounter name clashes with other variables or libraries. This can cause conflicts and errors.
4. **Performance and Implementation Complexity**: The global object in JavaScript can negatively impact performance and make the implementation of variable scoping more complicated.
5. **Less Modular Code**: Global variables can lead to less modular code, making it harder to reuse and maintain different parts of the program independently
### How to avoid global scope pollution
To avoid polluting the global scope in JavaScript, consider the following strategies:
1. **Use local variables**: Declare variables within functions or blocks to limit their scope and prevent them from being accessed globally. Use var, let, or const to declare variables within a specific scope, ensuring they are not accidentally made global
2. **Pass variables as function parameters:**: Instead of accessing variables directly from the outer scope, pass them as parameters to functions to maintain encapsulation and avoid global scope pollution.
3. **Use immediately invoked function expressions (IIFE)**: Wrap your code in an IIFE to create a new scope, preventing variables from being added to the global scope unless you explicitly expose them.
4. **Use modules**: Utilize module systems to encapsulate your code and prevent global scope pollution. Each module has its own scope, making it easier to manage and maintain your code.
## Further reading
- [JS: dont touch the global scope](https://lucybain.com/blog/2014/js-dont-touch-global-scope/)
- [Variables: Scopes, Environments, and Closures](https://exploringjs.com/es5/ch16.html)
- [JavaScript modules - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
- [Modules, introduction](https://javascript.info/modules-intro)