Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at ways to improve our JavaScript code.
Inheriting From Standard Classes
With the class syntax, we can create subclasses of standard classes easily.
For instance, we can create a subclass of the Array
constructor by writing:
class MyArray extends Array {}
const myArray = new MyArray(1, 2, 3);
Then myArray.length
is 3.
Since the Array
constructor is called when we call the MyArray
constructor, then length
property is set properly.
The [[Class]]
value of MyArray
is set to Array
so the length
is set properly.
If we get the prototype of myArray
:
Object.prototype.toString.call(myArray)
We get:
[object Array]
The following are the values of [[Class]]
for various built-in constructors:
Array
—[[Class]]
is'Array'
Boolean
—[[Class]]
is'Boolean'
Date
—[[Class]]
is'Date'
Error
—[[Class]]
is'Error'
Function
—[[Class]]
is'Function'
JSON
—[[Class]]
is'JSON'
Math
—[[Class]]
is'Math'
Number
—[[Class]]
is'Number'
Object
—[[Class]]
is'Object'
RegExp
—[[Class]]
is'RegExp'
String
—[[Class]]
is'String'
This type of inheritance can only be done with the class syntax.
The old constructor syntax wouldn’t set the [[Class]]
property properly.
Prototypes are an Implementation Detail
Prototypes have the properties that an object inherit from.
Objects are the interfaces.
We shouldn’t inspect the prototype structure of objects that we don’t control.
And we shouldn’t inspect properties that implement the internals of objects we don’t control.
If it’s something that we don’t control, then we can’t change them.
So we’ve to deal with them with our own code that we control.
No Reckless Monkey-Patching
Monkey-patching is changing the code on the fly.
JavaScript doesn’t prevent us from changing the properties of any object, including built-in objects.
For instance, we can add an instance method to the Array
constructor by writing:
Array.prototype.split = function(i) {
return [this.slice(0, i), this.slice(i)];
};
But other people may do the same thing.
So we may get properties and methods that we don’t expect in built-in objects.
And they can be removed and break a lot of code that uses it.
So we’ll run into problems if we add things to built-in objects that we don’t expect.
The better way to add our own code is to keep them separate from built-in objects.
For instance, we can write:
function split(arr, i) {
return [arr.slice(0, i), arr.slice(i)];
};
to create our own split
function.
However, one acceptable thing we can add that changes existing built-in objects is polyfills.
They are libraries that add functionality that should be supported in JavaScript engines in the future.
Their behavior is standardized so that we can use them to add methods in a safe way.
Conclusion
With the class syntax, we can inherit from standard classes.
Also, we shouldn’t inspect code that we don’t control since we can’t change them.
And we shouldn’t monkey-patch native built-in objects with our own code.