1. 程式人生 > >談談前端JavaScript 型別判斷typeof和instanceof的區別及一個型別判斷Util的簡單實現

談談前端JavaScript 型別判斷typeof和instanceof的區別及一個型別判斷Util的簡單實現

  instanceof和typeof運算子都能用來判斷一個變數是否為空或是什麼型別。typeof用以獲取一個變數的型別,typeof一般只能返回如下幾個結果果:number, boolean, string, function, object, undefined。我們可以使用typeof來獲取一個變數是否存在,如if(typeof a!=“undefined”){//TODO},對於Date, Array, Null等特殊物件使用typeof一律返回object,這正是typeof的侷限性。instanceof用於判斷一個變數是否某個物件的例項,如var a=new Array(); alert(a instanceof Array);會返回true,同時alert(a instanceof Object)也會返回true;這是因為Array是object的子類。

1、typeof運算子

  typeof是一元運算子,放在運算元前面,返回表示運算元型別的一個字串。任意運算元在typeof運算後返回值如下:

運算元 x typeof x example
undefined “undefined” var a; typeof a; //undefiend
null “object” var a = null; typeof a; //object
true “boolean” var a = true; typeof a; //boolean
數字或NaN “number” var a = “12” - 0; typeof a; //number
任意字串 “string” var a = 12 + “”; typeof a; //string
任意函式 “function” var a = function(){}; function b(){};
typeof a; typeof b;//function function
任意內建物件 “object” var a = new Date, b = new Array(1);
typeof a; type b; //object object

  通過上表我們可以看出typeof返回4類值:

  • 原始值:string, number, boolean
  • undefined
  • function
  • object:Date, Array等

注意function其實是object的一種,但是typeof返回function而不是object,需要注意,原因可以簡單理解為:function是可執行的,根據ECMAScript3規範,對於所有內建可執行物件,typeof運算子一律返回"function"。

typeof運算對於判斷運算元是原始值型別還是物件型別,尤其判斷變數是否定義過非常有用,但是對於判斷具體是Date還是Array還是其它就無能為力啦,需要instanceof運算子或其它技術手段實現。

2、instanceof運算子

  instanceof運算子希望左運算元是一個物件,右運算元標識物件型別的類。如果左側物件是右側類的例項,則返回true,否則返回false。通俗點理解就是:instanceof判斷一個物件是否為某一資料型別,或一個變數是否為一個物件的例項。看個案例:

var d = new Date;
d instanceof Date;		//true
d instanceof Object;		//true, 所有物件都是object的例項
d instanceof Number;		//false
var a = [1,2,3];
a instanceof Array;		//true
a instanceof Object;		//true, 所有陣列都是物件
a instanceof RegExp;		//false

  instanceof工作機制基於JavaScript原型鏈,類似Java繼承關係。為了計算表示式o instanceof f,首先計算f.prototype,然後在o的原型鏈中查詢f.prototype,如果找到,那麼o是f的一個例項,表示式返回true。如果f.prototype不在o的原型鏈中,那麼o就不是f的一個例項,表示式返回false。
判斷:o.proto.proto…會不會等於f.prototype, 看個案例:

function C(){} 
function D(){}

var o = new C(); 
console.log('o instanceof C: ', o instanceof C); 	// true, o.__proto__ == C.prototype
console.log('o instanceof D: ', o instanceof D); 	// false, D.prototype不在o的原型鏈上 
console.log('o instanceof Object: ', o instanceof Object); 	// true, o.__proto__.__proto__ == Object.prototype
console.log(C.prototype instanceof Object) 			// true, C.prototype.__proto__ = Object.prototype

C.prototype = {}; 
var o2 = new C(); 
console.log(o2 instanceof C); 		// true 
console.log("o instanceof C", o instanceof C);  //false, C.prototype指向了一個空物件,這個物件不在o的原型鏈上. 

D.prototype = new C();
var o3 = new D(); 
o3 instanceof D; 					// true, 
o3 instanceof C; 					// true, o3是D的例項,而D繼承C

3、型別判斷TypeUtil的簡單實現

我們可以通過Object.prototype.toString方法,判斷某個物件值屬於哪種內建型別,一個案例:

var TypeUtil = (function() {
  return {
    isString: function(str) {
      return Object.prototype.toString.call(str) === "[object String]";
    },
    isNumber: function(num) {
      return Object.prototype.toString.call(num) === "[object Number]";
    },
    isBoolean: function(flag) {
      return Object.prototype.toString.call(flag) === "[object Boolean]";
    },
    isFunc: function(fn) {
      return Object.prototype.toString.call(fn) === "[object Function]";
    },
    isArray: function(arr) {
      return Object.prototype.toString.call(arr) === "[object Array]";
    },
    isObject: function(obj) {
      return Object.prototype.toString.call(obj) === "[object Object]";
    }
  };
}());
console.log("TypeUtil.isString: ", TypeUtil.isString("1212")); //true
console.log("TypeUtil.isNumber: ", TypeUtil.isNumber(1212)); //true
console.log("TypeUtil.isBoolean: ", TypeUtil.isBoolean(true)); //true