liveBook · Manning

Feature detection

As explained in Secrets of the JavaScript Ninja, Second Edition

Checking whether a runtime environment supports a capability by testing for the feature itself.

When browser APIs differ, check for the capability your code needs rather than assuming every runtime offers the same interface. Feature detection tests whether an object or property exists, then uses that presence to infer support; the check is useful, but the inference can fail. section 14.3.2 section 14.2.4

Listing 14.1. Anticipating an upcoming API change
function bindEvent(element, type, handle) {
  if (element.addEventListener) {
    element.addEventListener(type, handle, false);                #A
  }
  else if (element.attachEvent) {
    element.attachEvent("on" + type, handle);                     #B
  }
}

The event-binding function prefers the standard API, falls back to the legacy one, and does nothing if neither is available. section 14.2.4

The same pattern can supply a polyfill: leave a built-in feature alone when present, and provide a fallback implementation when it is missing. For example, check for Array.prototype.find before adding a replacement. section 14.3.2

Listing 14.2. A polyfill for the Array.prototype.find method
if (!Array.prototype.find) {                                       #A
  Array.prototype.find = function(predicate) {                     #B
    if (this === null) {
      throw new TypeError('find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;                                #C
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {                             #D
      value = list[i];                                             #D
      if (predicate.call(thisArg, value, i, list)) {               #D
        return value;                                              #D
      }                                                            #D
    }                                                              #D
    return undefined;
  };
}

This listing guards an Array.prototype.find polyfill with a feature check and shows the fallback's predicate loop. section 14.3.2

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Defines presence checks and works through API selection and a polyfill, while noting that existence may not guarantee implied functionality.
Examples
Uses event-handler API selection and an Array.prototype.find fallback as concrete examples.
What you can do after
Apply capability checks to choose between standard and legacy event APIs or provide an Array.find fallback.
How it connects
Connects feature checks with polyfills, browser APIs, and cross-browser compatibility.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.