Home > Web Front-end > JS Tutorial > When JavaScript Feature Detection Fails

When JavaScript Feature Detection Fails

尊渡假赌尊渡假赌尊渡假赌
Release: 2025-02-22 09:57:12
Original
808 people have browsed it

When JavaScript Feature Detection Fails

Key Points

  • JavaScript feature detection (testing features that programmers want to use) is not always reliable. For example, test ActiveXObject in Internet Explorer for Ajax requests, HTML attributes mapped to DOM properties, assumptions about user behavior (such as detecting touch devices), etc.
  • When feature detection fails, browser detection is sometimes required. However, it is recommended to use proprietary object testing instead of navigator information and use it to exclude browsers rather than include them.
  • Be extremely careful when implementing browser detection. Always assume that it is fully consistent with feature testing and only seek browser detection if you know that a feature does not work as expected. Furthermore, the syntax used for object and feature testing can affect the success rate of detection, so choosing the right syntax is crucial.

Once upon a time, browser detection was the best skill of JavaScript programmers. If we know that some features work in IE5 but not in Netscape 4, we will test the browser and modify the code accordingly. For example:

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
Copy after login
Copy after login
Copy after login
Copy after login

But when I first joined the industry, the arms race had already begun! Vendors are adding extra values ​​to user agent strings, so they look like their competitors’ browsers, and their own. For example, this is Safari 5 for Mac:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
Copy after login
Copy after login
Copy after login
Copy after login

This will match tests for "Safari", "Webkit", and "KHTML" (the Konqueror code base that Webkit is based); but it also matches "Gecko" (which is Firefox's rendering engine), and of course "Mozilla" ” (For historical reasons, almost every browser claims to be Mozilla).

The purpose of adding all these values ​​is to circumvent browser detection. If the script assumes that only Firefox can handle specific features, Safari may be excluded, even if it may work. Don't forget that users can change their user agent themselves - I used to set my browser to recognize "Googlebot/1.0" so that I can access what the site owner thinks is for crawling only!

So, over time, this kind of browser detection has become an impossible mess and is largely out of use, replaced by something better—feature detection.

Feature detection is just to test the features we want to use. For example, if we need getBoundingClientRect (get the position of an element relative to the viewport), then it is important whether the browser supports it, not which browser it is; therefore, instead of testing supported The browser is worse than the test feature itself:

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
Copy after login
Copy after login
Copy after login
Copy after login
Browsers that do not support this function will return the "undefined" type, so the condition will not be passed. Without testing the script in any particular browser, we know that it either works correctly or fails silently.

Or we…?

But the truth is - feature detection is not entirely reliable - sometimes it fails. So let's look at some examples now and see what we can do to solve each case.

ActiveX Object

Perhaps the most famous example of feature detection failure is testing ActiveXObject for Ajax requests in Internet Explorer.

ActiveX is an example of late-bound objects, and the practical significance is that you can't know if it is supported until you try to use it . Therefore, if the user disables ActiveX, the following code will throw an error:

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
Copy after login
Copy after login
Copy after login
Copy after login
To fix this, we need to use exception handling -

try instantiate the object, catch any failures and handle it accordingly:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
Copy after login
Copy after login
Copy after login
Copy after login
HTML attribute mapped to DOM attribute

Attribute mapping is often used to test the support of APIs used with HTML5 properties. For example, check if an element with

supports draggable API by looking for draggable properties: [draggable="true"]

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
Copy after login
Copy after login
Copy after login
Copy after login
The problem here is that IE8 or earlier will automatically map all

HTML properties to DOM properties. This is why is so confusing in these older versions, because it does not return properties at all, but DOM properties. getAttributeThis means if we use an element that already has the

attribute:

Then even if they are not supported, IE8 or earlier will return

for
if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
Copy after login
Copy after login
Copy after login
.

trueAttribute can be anything: ("draggable" in element)

But the result will be the same - IE8 or earlier will return

for
if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
Copy after login
Copy after login
Copy after login
.

trueIn this case, the solution is to use an element that does not have that attribute for testing, the safest way is to use the created element: ("nonsense" in element)

Assumptions about user behavior

if ("draggable" in element) {
  // 浏览器支持拖放
}
Copy after login
Copy after login
You may have seen using the following code to detect touch devices:

Most touch devices implement manual delays before triggering a click event (usually around 300 milliseconds), which is to avoid clicking on elements while also clicking them. But this makes the application feel sluggish and unresponsive, so developers sometimes use this feature test to fork the event:

<div draggable="true"> ... </div>
Copy after login

However, this condition stems from a

error of the
<div nonsense="true"> ... </div>
Copy after login
- because the device supports touch, touch will be used. But what about touch screen laptops? The user may be touching the screen or using a mouse or trackpad; the code above cannot handle this, so clicking with the mouse will not perform anything.

In this case, the solution is not to test event support at all - instead bind two

events at the same time, and then use

to prevent the touch from generating clicks:

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
Copy after login
Copy after login
Copy after login
Copy after login

Things that don't work at all

Acknowledging this is painful, but sometimes what we don't need to test is not the feature - but the browser - because a particular browser claims to support something that doesn't work. A recent example is setDragImage() in Opera 12 (which is a way to drag and drop dataTransfer objects).

Feature test fails here because Opera 12 claims to support it; exception handling is not helpful, either, because it does not throw any errors. It just doesn't work:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
Copy after login
Copy after login
Copy after login
Copy after login

Now, if you just want to try to add a custom drag image and are happy to keep the default value without support (which will happen), then this may be fine. But what if your application does need custom images so that browsers that do not support it should use a completely different implementation (i.e., use custom JavaScript to implement all drag behavior)?

Or what if the browser implements certain features but there are unavoidable rendering errors? Sometimes we have no choice but to explicitly detect the problematic browser and exclude it from the features that it would have tried to support using it.

So the problem becomes - what is the safest way to achieve browser detection?

I have two suggestions:

    Prefer to proprietary object testing over navigator information.
  1. Use this to exclude browsers rather than include them.
For example, you can use

object detection Opera 12 or earlier, so we can use this exclusion to test draggable support: window.opera

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
Copy after login
Copy after login
Copy after login
Copy after login
It is better to use proprietary objects instead of standard objects, because when a new browser is released, the test results are unlikely to change. Here are some of my favorite examples:

if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
Copy after login
Copy after login
Copy after login
Object testing can also be used in conjunction with feature testing

to determine support for specific features in a specific browser, or in case of emergency, define more precise browser conditions:

We have noticed that user agent strings are an unreliable mess, but vendor strings are actually quite predictable and can be used to reliably test Chrome or Safari:
if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
Copy after login
Copy after login
Copy after login

The golden rule for all this is to be extremely careful. Make sure you test the conditions in as many browsers as possible and carefully consider their
if ("draggable" in element) {
  // 浏览器支持拖放
}
Copy after login
Copy after login
forward compatibility

-the goal is to use browser conditions to exclude browsers because there is already Known errors, not include them because of known features (this is the purpose of feature testing) Basically, always assume that the feature test is fully in line with - unless you know that this is not the case, then the feature will work as expected.

Select test syntax

Before ending, I want to check out the different types of syntax we can use for object and property testing. For example, in recent years, the following syntax has become common:

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
Copy after login
Copy after login
Copy after login
Copy after login

We were unable to use it in the past because IE5 and its similar products would throw errors due to syntax; but now we don't have to support these browsers, which is no longer a problem.

Essentially, it's exactly the same as the following, but it's shorter to write:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
Copy after login
Copy after login
Copy after login
Copy after login

However, test conditions usually rely on automatic type conversion:

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
Copy after login
Copy after login
Copy after login
Copy after login

We used this syntax earlier in some browser object tests (e.g. window.opera tests), which is safe because of how objects evaluate - any defined object or function will always be evaluated as true, and if it is undefined, it will be evaluated as false.

But we may be testing something that effectively returns null or empty strings, both of which evaluate to false. For example, the style.maxWidth attribute is sometimes used to exclude IE6:

if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
Copy after login
Copy after login
Copy after login

It will only evaluate to true if the maxWidth attribute is supported and the has the author defined value, so if we write the test like this, it may fail:

if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
Copy after login
Copy after login
Copy after login

The general rule is this: Relying on automatic type conversion is safe for objects and functions, but not necessarily safe for strings and numbers or values ​​that may be null.

That being said - if you can use it safely, do it because it is usually much faster in modern browsers (probably because they are optimized for this type of condition).

For more information on this, see: Automatic Type Conversion in the Real World.

Frequently Asked Questions about JavaScript Feature Detection

What is JavaScript feature detection and why is it important?

JavaScript feature detection is a technology used by developers to determine whether a user's browser supports a specific feature or API. This is crucial because not all browsers support all features of JavaScript. By using feature detection, developers can provide alternative solutions or fallbacks for unsupported features, ensuring that websites or applications run correctly on different browsers. This enhances the user experience and ensures compatibility.

How does JavaScript feature detection fail?

JavaScript feature detection may fail for a number of reasons. A common reason is that the feature detection code is incorrectly implemented. For example, if the code checks for properties that do not exist in the object, it will return undefined, resulting in a false negative. Another reason could be a browser quirk or error, which could cause feature detection to give inaccurate results.

What is the difference between feature detection and browser detection?

Feature detection involves checking whether a user's browser supports a specific feature or API, while browser detection recognizes the user's browser and version. While both techniques are designed to ensure compatibility and functionality, feature detection is often considered a better practice because it checks for features directly, rather than assuming its support based on browser type or version.

How to use JavaScript to detect mobile devices?

You can use the navigator.userAgent attribute in JavaScript to detect mobile devices. This property returns a string representing the browser's user agent header. By checking for specific keywords in this string (such as "Android", "iPhone", or "iPad"), you can determine if the user is on a mobile device.

What is Feature.js and how does it help with feature detection?

Feature.js is a lightweight, fast and simple JavaScript utility for feature detection. It provides an easy-to-use API that allows developers to test whether the browser supports specific features. This helps provide a backup solution or alternative solution for unsupported features, thereby enhancing compatibility and functionality of the website or application.

What is Modernizr and how does it help with feature detection?

Modernizr is a JavaScript library that helps developers take advantage of HTML5 and CSS3 features while maintaining compatibility with older browsers. It uses feature detection to check if the browser supports specific features and adds classes to HTML elements, allowing you to locate specific browser features in stylesheets or JavaScript.

How to use the device-detector-js package for feature detection?

The

device-detector-js package is a powerful tool for device detection. It parses user agent strings and detects smartphones, tablets, desktops, TVs and other devices. It also detects browsers, engines, operating systems, and other useful information. You can use this package to adjust the behavior of a website or application based on the detected devices.

What are some best practices for implementing feature detection?

Some best practices for implementing feature detection include: using reliable and tested libraries such as Modernizr or Feature.js, thoroughly testing your feature detection code on different browsers and devices, as unsupported Features provide alternative solutions or fallbacks and avoid assuming feature support based on browser type or version.

Can feature detection help improve website performance?

Yes, feature detection can help improve website performance. By detecting unsupported features and providing alternative solutions or fallback solutions, you can prevent unnecessary code from running in the browser. This reduces load time and improves overall performance of the website.

How to understand the latest features supported by different browsers?

As a result of the rapid development of web development, it can be challenging to understand the latest features supported by different browsers. However, resources such as Mozilla Developer Network (MDN), Can I Use, and JavaScript documentation can provide the latest information on feature support in different browsers.

The above is the detailed content of When JavaScript Feature Detection Fails. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template