Creating maintainable JavaScript code is important if want to keep using the code.
In this article, we’ll look at the basics of creating maintainable JavaScript code by looking at how to detect browsers.
Browser Detection
Browser detection is a tricky topic.
There’s no perfect way to detect the actual browser.
User-Agent Detection
One way to detect the browser is user-agent detection.
The client or server can look at the user-agent string to determine the browser that made the request.
The browser’s user-agent string can be found in the navigation.userAgent
property.
So we may think about writing something like:
if (navigator.userAgent.includes("MSIE")) {
// ...
} else {
// ...
}
We check for Internet Explorer by using the user-agent string.
The problem is that parsing the user-agent string is hard.
Also, browsers have copied each other to maintain compatibility.
With every new browser release, we need to update the user-agent detection code.
This added to the maintenance burden that we have to do.
User-agent string checking should be the last approach to check for the correct course of action.
If we check for user-agent strings, then we should only check the older browsers.
This is because newer browsers probably have the new features we want.
New features won’t be added to old browsers.
Feature Detection
Instead of checking the user-agent string, we should check whether the feature we want exists in the browser.
To do that, we can check for properties.
For instance, we can write:
if (typeof document.getElementById === 'function') {
// ...
}
to check that document.getElementById
is a function.
This way, we know exactly what we’re looking for exists or not.
It doesn’t rely on knowledge of which browser is used and only which features are available.
Therefore, it’s easy to support new browsers.
We should provide a logical fallback is there’s no feature available in the browser to provide the functionality that we want.
If we want to use newer features, then we’ve to different kinds of checks for different browsers’ implementations.
For instance, we may write:
function setAnimation(callback) {
if (window.requestAnimationFrame) {
return requestAnimationFrame(callback);
} else if (window.mozRequestAnimationFrame) {
return mozRequestAnimationFrame(callback);
} else if (window.webkitRequestAnimationFrame) {
return webkitRequestAnimationFrame(callback);
} else if (window.oRequestAnimationFrame) {
return oRequestAnimationFrame(callback);
} else if (window.msRequestAnimationFrame) {
return msRequestAnimationFrame(callback);
} else {
return setTimeout(callback, 0);
}
}
to check each browser’s implementation of the requestAnimation
method.
If none of the variants available, then we use the setTimeout
method.
Avoid Feature Inference
We should assume that if one feature is available, then the related features are available.
For instance, we shouldn’t assume that if document.getElementsByTagName()
is present, then document.getElementById()
is present.
This also applies to any other kind of object.
Avoid Browser Inference
Also, we shouldn’t infer the browser from a given feature.
So we shouldn’t write something like:
if (document.all) {
//...
} else {
//...
}
to infer that is document.all
exists, then IE is being used.
The code above isn’t an equivalent to:
const isIE = navigator.userAgent.includes("MSIE");
if (isIE) {
//...
} else {
//...
}
We can’t assume that if one feature exists, then our code is running on a given browser.
This is because the feature can be present in other browsers.
Conclusion
Browser detection is a tricky topic.
User-agent string detection isn’t very accurate.
But we can check for features to see if they’re present before we use them.