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
Section titled “The navigator Object”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.
Common navigator Properties:
Section titled “Common navigator Properties:”| Property | Description |
|---|---|
navigator.userAgent | A 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.language | A string representing the preferred language of the user, usually the language of the browser UI (e.g., “en-US”). |
navigator.languages | An array of strings representing the user’s preferred languages, sorted by preference. |
navigator.onLine | A boolean value indicating whether the browser currently has an internet connection (true) or not (false). |
navigator.platform | A 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.cookieEnabled | A boolean indicating whether cookies are enabled in the browser. |
navigator.geolocation | Returns a Geolocation object that can be used to locate the user’s position (requires user permission). |
navigator.mediaDevices | Provides access to connected media input devices like cameras and microphones (requires user permission). |
navigator.connection | Provides 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.
The Fallacy of Browser Sniffing
Section titled “The Fallacy of Browser Sniffing”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 CONTROLfunction 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.
Best Practice: Feature Detection
Section titled “Best Practice: Feature Detection”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.
Examples of Feature Detection:
Section titled “Examples of Feature Detection:”// 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 APIif ('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 elementif (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.
Polyfills and Transpilers
Section titled “Polyfills and Transpilers”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
Promisepolyfill would implement thePromiseobject ifwindow.Promiseis 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.