search
HomeWeb Front-endJS TutorialWhen JavaScript Feature Detection Fails

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
}

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>

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") {
  // 浏览器支持此函数
}
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
}
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>
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") {
  // 浏览器支持此函数
}
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");
}
.

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) {
    //... 我们有一个请求对象
  }
}
.

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) {
  // 浏览器支持拖放
}
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>

However, this condition stems from a

error of the
<div nonsense="true"> ... </div>
- 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
}

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>

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") {
  // 浏览器支持此函数
}
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");
}
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) {
    //... 我们有一个请求对象
  }
}

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) {
  // 浏览器支持拖放
}
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
}

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>

However, test conditions usually rely on automatic type conversion:

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

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");
}

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) {
    //... 我们有一个请求对象
  }
}

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
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
JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

JavaScript Frameworks: Powering Modern Web DevelopmentJavaScript Frameworks: Powering Modern Web DevelopmentMay 02, 2025 am 12:04 AM

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

The Relationship Between JavaScript, C  , and BrowsersThe Relationship Between JavaScript, C , and BrowsersMay 01, 2025 am 12:06 AM

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

Node.js Streams with TypeScriptNode.js Streams with TypeScriptApr 30, 2025 am 08:22 AM

Node.js excels at efficient I/O, largely thanks to streams. Streams process data incrementally, avoiding memory overload—ideal for large files, network tasks, and real-time applications. Combining streams with TypeScript's type safety creates a powe

Python vs. JavaScript: Performance and Efficiency ConsiderationsPython vs. JavaScript: Performance and Efficiency ConsiderationsApr 30, 2025 am 12:08 AM

The differences in performance and efficiency between Python and JavaScript are mainly reflected in: 1) As an interpreted language, Python runs slowly but has high development efficiency and is suitable for rapid prototype development; 2) JavaScript is limited to single thread in the browser, but multi-threading and asynchronous I/O can be used to improve performance in Node.js, and both have advantages in actual projects.

The Origins of JavaScript: Exploring Its Implementation LanguageThe Origins of JavaScript: Exploring Its Implementation LanguageApr 29, 2025 am 12:51 AM

JavaScript originated in 1995 and was created by Brandon Ike, and realized the language into C. 1.C language provides high performance and system-level programming capabilities for JavaScript. 2. JavaScript's memory management and performance optimization rely on C language. 3. The cross-platform feature of C language helps JavaScript run efficiently on different operating systems.

Behind the Scenes: What Language Powers JavaScript?Behind the Scenes: What Language Powers JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript runs in browsers and Node.js environments and relies on the JavaScript engine to parse and execute code. 1) Generate abstract syntax tree (AST) in the parsing stage; 2) convert AST into bytecode or machine code in the compilation stage; 3) execute the compiled code in the execution stage.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool