老話題了,各種方案和相關討論都不少,簡單總結下:
JavaScript裡只有五種基本數據類型:number, string, boolean, null, undefined. 其它的都是復合數據類型object.
值和數據類型是兩碼事。比如:null是null類型的唯一值,undefined是undefined類型的唯一值,就如true和false是boolean類型的唯兩值一樣。
可以用typeof檢測出以下6種數據類型:number, string, boolean, undefined, object, function.
注意:typeof null == “object”. null類型的唯一值null的類型是object類型。(很拗口,但事實就是這樣)
因此,對於五種基本數據類型來說,用下面的代碼就可以檢測出來:
// 獲取變量o的數據類型 function type(o) { return (o === null) ? 'null' : typeof(o); }
typeof只能檢測基本數據類型,對於復合數據類型,除了function,都通通返回'object'.
instanceof可以檢測某個對象是不是另一個對象的實例,注意instanceof的右操作數必須為對象:
alert(1 instanceof Number); // false alert({} instanceof Object); // true
instanceof還可以檢測父類型:
function Animal() {}; function Pig() {}; Pig.prototype = new Animal(); alert(new Pig() instanceof Animal); // true
可以看出,instanceof不適合用來檢測一個對象本身的類型。
JavaScript裡的所有對象都擁有一個constructor屬性,但JavaScript裡並非一切都是對象:
alert(1.constructor); // 報錯 var o = 1; alert(o.constructor); // Number o = null; // or undefined alert(o.constructor); // 報錯 alert({}.constructor); // Object alert(true.constructor); // Boolean
可以看出,null和undefined沒有constructor,number和string數據類型的字面量,也沒有constructor,但number和string數據類型的變量有constructor(在尋找constructor屬性時,會自動轉換成Number或String對象)。
下面是Johg Resig《Pro JavaScript Techniques》書中的一張表:
這樣,對於復合數據類型,我們可以采用下面的方法檢測:
... isArray: function(arr) { return !!arr && arr.constructor == Array; } ...
jQuery 1.2中采用的就是上面的代碼。
一切看起來很完美,然而不安分的iframe總喜歡來搗點鬼:
// 請在非ie浏覽器中運行 var iframe = document.createElement('iframe'); document.body.appendChild(iframe); var xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1, 2, 3); // [1,2,3] alert(arr.constructor === Array); // false
原因很簡單:不同frame中的Array擁有不同的constructor.
在犀牛書裡,提到一句老話:“如果走路像鴨子,叫聲也像鴨子,那它就是一個鴨子!” 換言之,對於Array來說,如果一個對象有splice和join屬性,那它就是Array. 這就是Duck Typing:
function isArray(o) { return o != null && typeof o === ‘object’ && 'splice' in o && 'join' in o; }
上面是Prototype 1.6中的代碼。
顯然,鴨子檢測很容易誤把自造的天鵝也當成鴨:
alert(isArray({'splice': '', 'join': ''})); // true
鴨子檢測的一個用途是,可以用來檢測類似對象,比如類數組:
function isArrayLike(x) { if (x instanceof Array) return true; // Real arrays are array-like if (!('length' in x)) return false; // Arrays must have a length property if (typeof x.length != 'number') ret