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.
No Unnecessary State
APIs can be classified as stateful or stateless.
A stateless API provides functions or methods whose behavior depends on inputs.
They don’t change the state of the program.
If we change the state of a program, then the code is harder to trace.
A part of a program that changes the state is a stateful API.
Stateless APIs are easier to learn and use, more self-documenting, and less error-prone.
They’re also easier to test.
This is because we get some output when we pass in some input.
This doesn’t change because of the external state.
We can create stateless APIs with pure functions.
Pure functions return some output when given some input.
When the inputs are the same in 2 different calls, we get the same output each time.
So instead of writing:
c.font = "14px";
c.textAlign = "center";
c.fillText("hello, world!", 75, 25);
We write:
c.fillText("14px", "center", "hello, world!", 75, 25);
The 2nd case is a function that takes inputs and doesn’t depend on the font
and textAlign
property as it does in the previous example.
Stateless APIs are also more concise.
Stateful APIs led to a proliferation of additional statements to set the internal state of an object.
Use Structural Typing for Flexible Interfaces
JavaScript objects are flexible, so we can just create object literals to create interfaces with items we want to expose to the public.
For instance, we can write:
const book = {
getTitle() {
/* ... */
},
getAuthor() {
/* ... */
},
toHTML() {
/* ... */
}
}
We have some methods that we want to expose to the public.
We just provide this object as an interface for anything that uses our library.
This is the easiest way to create APIs that the outside world can use.
Distinguish Between Array and Array-Like Objects
JavaScript has arrays and array-like objects.
They aren’t the same.
Arrays have their own methods and can store data in sequence.
They’re also an instance of the Array
constructor.
Array-like objects don’t have array methods.
To check if something is an array, we call the Array.isArray
method to check.
If it return false
, then it’s not an array.
Array-like objects can be iterable or not.
If they’re iterable, then we can convert them to an array with the spread operator.
For instance, we can convert NodeLists and the arguments
object to an array:
[...document.querySelectorAll('div')]
[...arguments]
We convert the NodeList and the arguments
object to an array.
If it’s a non-iterable array-like object, which is one with non-negative integer keys and a length
property, we can use the Array.from
method to do the conversion.
For instance, we can write:
const arr = Array.from({
0: 'foo',
1: 'bar',
length: 2
})
Then arr
would be:
["foo", "bar"]
Conclusion
We shouldn’t have unnecessary states in our program.
Also, duck typing is good for identifying types.
And we should distinguish between array and array-like objects.