Sometimes the name of a proposed feature (a method, a global variable, etc.) clashes with existing code and has to be changed. This blog post explains how that can happen and lists features that were renamed.
Table of contents:
Evolving JavaScript: Don’t break the web!
One core principle for evolving JavaScript is to not “break the web”: All existing code must continue to work after new features are added to the language.
The downside is that existing quirks can’t be removed from the language. But the upsides are considerable: Old code continues to work, upgrading to new ECMAScript versions is simple, etc.
For more information on this topic, consult section “Evolving JavaScript: Don’t break the web” in “JavaScript for impatient programmers”.
When a name is chosen for new feature such as a method name, one important test is to add that feature in a nightly edition of a browser and check if any websites exhibit bugs. The next sections cover four sources of conflict where that was the case in the past and features had to be renamed.
Source of conflict: adding methods to built-in prototypes
In JavaScript, we can add methods to built-in values by changing their prototypes:
Array.prototype.myArrayMethod = function () {
return this.join('-');
};
assert.equal(
['a', 'b', 'c'].myArrayMethod(), 'a-b-c'
);
String.prototype.myStringMethod = function () {
return '¡' + this + '!';
};
assert.equal(
'Hola'.myStringMethod(), '¡Hola!'
);
It’s fascinating that the language can be changed in this manner. This kind of runtime modification is called a monkey patch. The next subsection explains that term. Then we’ll look at the downsides of such modifications.
Term: monkey patches
If we add methods to built-in prototypes, we are modifying a software system at runtime. Such modifications are called monkey-patches. I try to avoid jargon, including this term, but it’s good to be aware of it. There are two possible explanations for its meaning (quoting Wikipedia):
-
It “seems to have come from an earlier term, guerrilla patch, which referred to changing code sneakily – and possibly incompatibly with other such patches – at runtime. The word guerrilla, homophonous with gorilla (or nearly so), became monkey, possibly to make the patch sound less intimidating.”
-
It “refers to ‘monkeying about’ with the code (messing with it).”
Reasons against changing built-in prototypes
With any kind of global namespace, there is always a risk of name clashes. That risk goes away when there are mechanisms to resolve conflicts – for example:
-
Global modules are identified via bare module specifiers or URLs. Name clashes among the former are prevented via the npm registry. Name clashes among the latter are prevented via domain name registries.
-
Symbols were added to JavaScript to avoid name clashes between methods. For example, any object can become iterable by adding a method whose key is
Symbol.iterator
. Since each symbol is unique, this key never clashes with any other property key.
However, methods with string keys can cause name clashes:
- Different libraries might use the same name for methods they add to
Array.prototype
. - If a name is already used by a library anywhere, it can’t be used for a new feature of JavaScript’s standard library anymore. There are several cases where that was an issue. They are described in the next section.
Ironically, being careful with adding a method can make matters even worse – for example:
if (!Array.prototype.libraryMethod) {
Array.prototype.libraryMethod = function () { };
}