javascript的變量類型分爲原始類型和引用類型。javascript
原始類型又有5種:java
number數組
string函數
booleanprototype
null指針
undefinedcode
引用類型有:對象
Function繼承
Arrayip
Date
Object
RegExp
而檢測這些類型的變量有3種辦法:typeof
,instanceof
,Object.prototype.toString.call
。讓我來一一例舉,廢話很少說,上代碼。
//首先是typeof var obj = 1; typeof obj; //"number" obj = "abc" typeof obj; //"string" obj = false typeof obj; //"boolean" obj = undefined; typeof obj; //"undefined" obj = null; typeof obj; //"object",WTF,其實這是js的一個bug,人艱不拆 T_T obj = function(){}; typeof obj; //"function" obj = []; typeof obj; //"object" obj = {}; typeof obj; //"object" obj = /w/g; typeof obj //"object"
從上面咱們能夠得出type能檢測原始類型number
,string
,boolean
,undefined
,引用類型的function
。這裏容我邪惡的笑一笑。
而關於引用類型,還能夠嘗試下instanceof
操做符。
var obj = function(){}; obj instanceof Function; //true obj = []; obj instanceof Array; //true obj = {}; obj instanceof Object; //true obj = new Date() obj instanceof Date; //true obj = /w/g; obj instanceof RegExp; //true //....橋豆麻袋, 事情其實還沒完呢 obj = []; obj instanceof Object; //true 草草嗒,全部引用類型其實都是繼承自Object對象的,因此你懂的。
incetanceof 操做符能鑑別引用類型,惋惜有個缺憾是,若是想鑑別一個變量object類型而不是其餘的function
,array
,date
什麼的,仍然須要花一番力氣。
這裏咱們是否是漏了什麼,若是..
var obj = new String('abc'); typeof obj; //"object" 。 obj instanceof String; //true 。
天了個擼,不能愉快玩耍了。要解釋這個, 就得解釋js裏變量的賦值規則。
原始類型的變量直接保存原始值,而不是一個只想對象的指針。若是一個變量賦值給另外一個變量,那麼每一個變量都它本身的一份數據拷貝,並不會相互影響。
引用類型的變量保存的是一個指向內存中實際對象所在的指針(或者說引用)。所以當你將一個對象賦值給變量時,實際是賦值給這個變量一個指針。意味着將一個變量賦值給另外一個變量時,兩個變量指向的是內存中同一個對象。
var obj = 'abc'; obj.something = 1; var firstChar = obj.charAt(0); //"a" console.log(obj.something); //undefined //實際上js作了這樣的處理 var obj = 'abc'; var temp = new String(obj); var firstChar = temp.charAt(0); //"a" temp.something = 1; temp = null; console.log(obj.something); //undefined
建立了一個臨時的引用類型變量去訪問屬性,修改屬性,而後就被釋放了。阿咧,扯遠了,這和咱們這片的內容啥關係。。
總而言之,若是指定obj = "abc"
則obj保存的實際上就是abc的值,是一個基本類型。而若是指定obj = new String('abc')
那麼obj實際上保存的是一個指向字符串對象的指針。因此就不難理解二者對於typeof
和instanceof
的差異了
額,讀者:「說了這麼多,你有沒有一種萬全的手段哇」。好吧, 咱們來一個簡單又粗暴的鑑別手段。
var obj = 1; Object.prototype.toString.call(obj) === '[object Number]'; //true obj = new Number(1); Object.prototype.toString.call(obj) === '[object Number]'; //true obj = []; Object.prototype.toString.call(obj) === '[object Array]'; //true obj = new Array(); Object.prototype.toString.call(obj) === '[object Array]'; //true Object.prototype.toString.call(obj) === '[object Object]'; //false
這個方法是否是很好用呢, 哇哈哈哈哈。
總結概括了下,我列舉了一些校驗函數:
//低版本ie中undefined變量能夠被修改,因此使用void 0 獲取真實的undefined值, var isUndefined = function(obj) { //or: return typeof obj === 'undefined'; return obj === void 0; }; //typeof null 的結果是"object"。 var isNull = function(obj) { return obj === null; }; // boolean值,number值和string值須要考慮兩種狀況,值爲字面量時使用typeof和Object.prototype.toString能檢測; // 值爲構造函數構建的時候須要使用Object.prototype.toString或者instanceof檢測 var isBoolean = function(obj) { return Object.prototype.toString.call(obj) == '[object Boolean]'; }; var isNumber = function(obj) { return Object.prototype.toString.call(obj) == '[object Number]'; }; var isString = function(obj) { return Object.prototype.toString.call(obj) == '[object String]'; }; var isNaN = function(obj) { return obj !== obj; }; //typeof 操做符在引用類型的變量裏能對function有效。 var isFunction = function(obj) { //or: return Object.prototype.toString.call(obj) == '[object Function]'; return typeof obj === 'function'; }; var isDate = function(obj) { return Object.prototype.toString.call(obj) == '[object Date]'; } var isArray = function(obj) { return Object.prototype.toString.call(obj) == '[object Array]'; } var isObject = function(obj) { //or: return obj === Object(obj); return Object.prototype.toString.call(obj) == '[object Object]'; } var isRegExp = function(obj) { //or: return obj === Object(obj); return Object.prototype.toString.call(obj) == '[object RegExp]'; } var has = function(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); }; //判斷數組,字符串,對象是否爲空 var isEmpty = function(obj) { if (obj == null) return true; if (isArray(obj) || isString(obj)) return obj.length === 0; for (var key in obj) if (has(obj, key)) return false; return true; };