Tip for checking if a function is native to JavaScript

  • 2020-05-16 06:15:18
  • OfStack

In my development work, I often encounter situations where I need to determine whether a function is a native function of JavaScript or not. Sometimes, this is a very necessary task, and you need to know whether the function is provided by the browser itself or packaged by a third party and disguised as a native function. Of course, the best way to do this is to look at the return value of the toString method that executes this function.

The JavaScript

The way to do this is simple:


function isNative(fn) {
 return (/\{\s*\[native code\]\s*\}/).test('' + fn);
}

The toString method returns the string form of the method, and then USES the regular expression to determine the characters contained within.

A more robust approach

Lodash founder John-David Dalton found a better solution:


;(function() {   // Used to resolve the internal `[[Class]]` of values
  var toString = Object.prototype.toString;
 
  // Used to resolve the decompiled source of functions
  var fnToString = Function.prototype.toString;
 
  // Used to detect host constructors (Safari > 4; really typed array specific)
  var reHostCtor = /^\[object .+?Constructor\]$/;   // Compile a regexp using a common native method as a template.
  // We chose `Object#toString` because there's a good chance it is not being mucked with.
  var reNative = RegExp('^' +
    // Coerce `Object#toString` to a string
    String(toString)
    // Escape any special regexp characters
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // Replace mentions of `toString` with `.*?` to keep the template generic.
    // Replace thing like `for ...` to support environments like Rhino which add extra info
    // such as method arity.
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
 
  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // Use `Function#toString` to bypass the value's own `toString` method
      // and avoid being faked out.
      ? reNative.test(fnToString.call(value))
      // Fallback to a host object check because some environments will represent
      // things like typed arrays as DOM methods which may not conform to the
      // normal native pattern.
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }
 
  // export however you want
  module.exports = isNative;
}());

Now you can see, it's complicated, but it's more powerful. Of course, this is not for security purposes, it just gives you information about whether it's a native function or not.


Related articles: