js判斷一個函式是內建還是自定義程式碼例項

螞蟻小編發表於2017-03-27

本章節介紹一下如何判斷一個函式是內建的還是使用者自定義的,這個在實際編碼中也是有需求的。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼
function isNative(fn){    
  return (/\{\s*\[native code\]\s*\}/).test(''+ fn); 
}
console.log(isNative(String.toString));

上面的程式碼實現了我們的要求,原理也非常的簡單,如下程式碼:

[JavaScript] 純文字檢視 複製程式碼
[].toString()

toString()函式結構圖示如下:

a:3:{s:3:\"pic\";s:43:\"portal/201703/27/120614h3zm4xghzgmgglmg.jpg\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

升級版本:

[JavaScript] 純文字檢視 複製程式碼
;(function(){ 
  // 取得Object的toString方法,用於處理傳入引數value的內部(internal) `[[Class]]` 
  var toString = Object.prototype.toString; 
 
  // 取得原始的Function的toString方法,用於處理functions的反編譯程式碼 
  var fnToString = Function.prototype.toString; 
 
  // 用於檢測 宿主物件構造器(host constructors), 
  // (Safari > 4; 真的輸出特定的陣列,really typed array specific) 
  var reHostCtor = /^\[object .+?Constructor\]$/; 
 
  // 使用RegExp將常用的native方法編譯為正則模板. 
  // 使用 `Object#toString` 是因為一般他不會被汙染 
  var reNative = RegExp('^' + 
  // 將 `Object#toString` 強轉為字串 
  String(toString) 
  // 對所有正規表示式相關的特殊字元進行轉義 
  .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&') 
  // 為了保持模板的通用性,將 `toString` 替換為 `.*?` 
  // 將`for ...`之類的字元替換,相容Rhino等環境,因為他們會有額外的資訊,如方法的引數數量. 
  .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') 
  // 結束符 
  + '$'); 
 
  function isNative(value){ 
    // 判斷 typeof 
    var type = typeof value; 
    return type == 'function'
    // 使用 `Function#toString`原生方法來呼叫, 
    // 而不是 value 自己的 `toString` 方法, 
    // 以免被偽造所欺騙. 
    ? reNative.test(fnToString.call(value)) 
    // 如果type 不是'function', 
    // 則需要檢查宿主物件(host object)的情形, 
    // 因為某些(瀏覽器)環境會將 typed arrays 之類的東西當作DOM方法 
    // 此時可能不匹配標準的Native正則模式 
    : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; 
  }; 
 
  // 可以將 isNative 賦值給你想要的變數/物件 
  window.isNative = isNative; 
}());

相關文章