関数がJavaScript原生関数かどうかを検出するためのテクニック

2432 ワード

私の開発の仕事の中でよく発生します.JavaScript原生関数かどうかを判断する必要があります.時にはこれは必要な仕事です.この関数はブラウザ自身が提供したのか、それとも第三者がカプセル化し、原生関数に偽装したのかを知る必要があります.もちろん、この関数を実行するためのtoString法の戻り値を調べるのが一番良い方法です.
The JavaScript
このタスクを完了する方法はとても簡単です.
 
  
function isNative(fn) {
 return (/\{\s*\[native code\]\s*\}/).test('' + fn);
}
Stringメソッドはこの方法の文字列形式を返し、正規表現でその中に含まれている文字を判断します.
もっと強い方法
Lodashの創始者John-David Daltonはより良い方案を見つけました.
 
  
;(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;
}());

今はあなたも見ました.複雑ですが、もっと強いです.もちろん、これは安全防護のためではなく、原生関数かどうかの関連情報を提供するだけです.