1. 程式人生 > 實用技巧 >判斷資料型別

判斷資料型別


/**
 * 判斷一個 變數 的型別,是 陣列、字串、還是物件或者函式等複雜型別。
 */

//  首先宣告一些變數
const str = "string",
  num = 12,
  isBool = true,
  isUndefined = undefined,
  isNull = null,
  obj = { name: "tom" },
  arr = [1],
  fun = () => {};

/**
 * 先看最簡單的 typeof 方法
 */

console.log(typeof str);
console.log(typeof num);
console.log(typeof isBool);
console.log(typeof isUndefined);
console.log(typeof isNull);
console.log(typeof obj);
console.log(typeof arr);
console.log(typeof fun);

/**
 * 輸出:string
 * number
 * boolean
 * undefined
 * object
 * object
 * object
 * function
 *
 * typeof 能判斷簡單型別的變數,但是對於引用型別的陣列,物件等卻無法區別
 * 都會識別為 object
 *
 */

/**
 * 使用 instanceof 方法
 */

console.log(str instanceof String); // false
console.log(num instanceof Number); // false
console.log(isBool instanceof Boolean); // false
// console.log(isUndefined instanceof undefined); // 報錯
// console.log(isNull instanceof null); // 報錯
console.log(obj instanceof Object); // true
console.log(arr instanceof Object); // true
console.log(arr instanceof Array); // true
console.log(fun instanceof Object); // true
console.log(fun instanceof Function); // true

/**
 * 從上面結果可以看出:
 *  對於簡單型別的字面量宣告,使用 instanceof 方法無法判斷型別
 *  對於複雜型別 instanceof 方法對於 Object 都會返回true,因為 陣列,函式本質來說都是物件。
 * instanceof 方法的作用是:檢測建構函式的 prototype 屬性是否出現在某個例項物件的原型鏈。
 * 即,fun instanceof Object 說明 fun 在 Object 的原型鏈上。並不是一個物件。
 * arr, fun 都會沿著原型鏈找到 Object 所以,也會返回true,使用時要注意。
 */

let str1 = new String("12");
console.log(`這是一個字串:${str1}`); // 這是一個字串:12
console.log(typeof str1); // object
console.log(str1 instanceof String); // true
/**
 * 此時 str1 能沿著原型鏈找到 String
 */

/**
 * 使用 原型方法 進行判斷
 */

console.log(Object.prototype.toString.call(str)); // [object String]
console.log(Object.prototype.toString.call(num)); // [object String]
console.log(Object.prototype.toString.call(isBool)); //
console.log(Object.prototype.toString.call(isUndefined)); //
console.log(Object.prototype.toString.call(isNull)); //
console.log(Object.prototype.toString.call(obj)); //
console.log(Object.prototype.toString.call(arr)); //
console.log(Object.prototype.toString.call(fun)); //
/**
 * [object String]
 * [object Number]
 * [object Boolean]
 * [object Undefined]
 * [object Null]
 * [object Object]
 * [object Array]
 * [object Function]
 *
 * 利用原型上的方法可以正確的判斷出元素型別
 *
 */

/**
 * 上述三種方法的優劣:
 *    Array.isArray 優於 instanceof, 因為Array.isArray能檢測iframes。
 *
 *    Objec.prototype.toString.call() 對於所有的基本資料型別都能進行判斷,包括 undefined 、null。常用於判斷瀏覽器內建物件。
 *
 *    instanceof  的內部機制是通過判斷物件的原型鏈中是不是能找到型別的 prototype。
 *    使用 instanceof判斷一個物件是否為陣列,instanceof 會判斷這個物件的原型鏈上是否會找到對應的 Array 的原型,找到返回 true,否則返回 false。
 *    instanceof 只能用來判斷物件型別,原始型別不可以。並且所有物件型別 instanceof Object 都是 true
 *
 *    Array.isArray()是ES5新增的方法,當不存在 Array.isArray()
 *    可以用 Object.prototype.toString.call() 實現。如下例子:
 */

if (!Array.isArray) {
  Array.isArray = function (arg) {
    return Object.prototype.toString.call(arg) == "[object Array]";
  };
}

// Array.isArray 的效能最好,instanceof 比 toString.call 稍微好了一點點。