Skip to content

ES6 - Browsers

ES6+ and Browser Environment Considerations

Section titled “ES6+ and Browser Environment Considerations”

While ES6 (ECMAScript 2015) and later versions of JavaScript are now widely supported by modern browsers, understanding the browser environment, its APIs, and how to write compatible code remains important. This involves knowing about the navigator object and, more crucially, employing feature detection over browser sniffing.

The navigator object is a property of the window object and contains information about the browser (the user agent). While it offers various properties, relying on them for controlling application logic (browser sniffing) is generally discouraged.

PropertyDescription
navigator.userAgentA string containing the user-agent header sent by the browser to the server. Often complex and can be spoofed. Primarily useful for analytics or debugging, not for feature detection.
navigator.languageA string representing the preferred language of the user, usually the language of the browser UI (e.g., “en-US”).
navigator.languagesAn array of strings representing the user’s preferred languages, sorted by preference.
navigator.onLineA boolean value indicating whether the browser currently has an internet connection (true) or not (false).
navigator.platformA string identifying the platform the browser is running on (e.g., “Win32”, “MacIntel”, “Linux x86_64”). Can be misleading and less reliable than specific feature checks.
navigator.cookieEnabledA boolean indicating whether cookies are enabled in the browser.
navigator.geolocationReturns a Geolocation object that can be used to locate the user’s position (requires user permission).
navigator.mediaDevicesProvides access to connected media input devices like cameras and microphones (requires user permission).
navigator.connectionProvides information about the system’s connection, such as the current effective connection type (e.g., ‘4g’). (Experimental, support varies)

Deprecated or Less Reliable navigator Properties:

Older tutorials might mention properties like navigator.appName, navigator.appCodeName, or navigator.appVersion. These are largely deprecated or return fixed values for compatibility reasons (e.g., appName often returns “Netscape” regardless of the browser) and should not be used for determining browser capabilities.

Browser sniffing involves checking the navigator.userAgent string to identify the browser and its version, then altering code behavior based on this detection. This practice is highly discouraged for several reasons:

  • Fragility: User-agent strings can be easily changed by the user or browser extensions.
  • Inaccuracy: Browsers might lie in their user-agent strings to bypass poorly written sniffing code on websites.
  • Maintenance Nightmare: New browsers and versions are released frequently, requiring constant updates to sniffing logic.
  • Focus on Implementation, Not Features: Sniffing assumes a certain browser has or lacks a feature, which might not always be true or could change in future versions.

Example of (Discouraged) Browser Sniffing:

Section titled “Example of (Discouraged) Browser Sniffing:”
// THIS IS AN EXAMPLE OF WHAT *NOT* TO DO FOR FEATURE CONTROL
function oldBrowserDetection() {
const userAgent = navigator.userAgent;
if (userAgent.includes('MSIE') || userAgent.includes('Trident/')) {
console.log('This might be Internet Explorer.');
// ... apply IE-specific logic (outdated approach)
} else if (userAgent.includes('Firefox')) {
console.log('This might be Firefox.');
} else if (userAgent.includes('Chrome')) {
console.log('This might be Chrome.');
} else {
console.log('Unknown browser or modern Edge (Chromium-based).');
}
}
oldBrowserDetection();

The code above attempts to identify the browser. However, a modern Chromium-based Edge browser would also contain ‘Chrome’ in its user agent, leading to potential misidentification if the logic isn’t carefully crafted and constantly updated.

Instead of asking “Which browser is this?”, ask “Does this browser support the feature I need?”. This is feature detection. You directly check if an object, method, or property exists and behaves as expected before using it.

// Check for Promise support (an ES6 feature)
if (window.Promise) {
console.log('Promises are supported.');
// Use Promises
} else {
console.log('Promises are NOT supported. Consider a polyfill or alternative.');
// Fallback logic
}
// Check for Geolocation API
if ('geolocation' in navigator) {
console.log('Geolocation API is available.');
navigator.geolocation.getCurrentPosition(position => {
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
}, error => {
console.error('Error getting location:', error.message);
});
} else {
console.log('Geolocation API is not available.');
}
// Check for a specific method on an element (e.g., requestFullscreen)
const myElement = document.documentElement; // Or any other element
if (myElement.requestFullscreen) {
console.log('Element supports requestFullscreen.');
// myElement.requestFullscreen(); // Example usage
} else if (myElement.mozRequestFullScreen) { // Firefox specific (older)
console.log('Element supports mozRequestFullScreen.');
// myElement.mozRequestFullScreen();
} else if (myElement.webkitRequestFullscreen) { // Webkit specific
console.log('Element supports webkitRequestFullscreen.');
// myElement.webkitRequestFullscreen();
} else if (myElement.msRequestFullscreen) { // IE/Edge specific (older)
console.log('Element supports msRequestFullscreen.');
// myElement.msRequestFullscreen();
} else {
console.log('Fullscreen API not supported on this element.');
}

Feature detection leads to more robust, future-proof, and maintainable code because it focuses on actual capabilities rather than assumptions based on browser identity.

When a modern JavaScript feature is not available in older browsers that you need to support:

  • Polyfills: A piece of code (JavaScript) that provides the functionality of a modern API or feature in older browsers that do not have it natively. For example, a Promise polyfill would implement the Promise object if window.Promise is undefined.
  • Transpilers: Tools like Babel convert modern JavaScript code (e.g., ES6+ syntax like arrow functions, classes) into an older version of JavaScript (e.g., ES5) that has wider browser compatibility. This allows developers to write modern code while ensuring it runs in more environments.

Using feature detection, polyfills, and transpilers allows developers to leverage modern JavaScript capabilities while gracefully handling environments where those features are not natively supported.