JS 類型檢測方法


簡介

javascript的變量類型分為原始類型和引用類型。

  • 原始類型有6種, 注意多了 Symbol
    • Number
    • String
    • Boolean
    • Null
    • Undefined
    • Symbol
  • 引用類型包括
    • Function
    • Array
    • Date
    • Object
    • RegExp

而檢測這些類型的變量有3種辦法:typeofinstanceofObject.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 = Symbol();
typeof obj; //"symbol"

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
//....wait for it, 事情其實還沒完呢
obj = [];
obj instanceof Object; //true  所有引用類型其實都是繼承自Object對象的,所以你懂的。

incetanceof 操作符能鑒別引用類型,可惜有個缺憾是,如果想鑒別一個變量object類型而不是其他的functionarraydate什么的,仍然需要花一番力氣。

這里我們是不是漏了什么,如果..

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實際上保存的是一個指向字符串對象的指針。所以就不難理解兩者對於typeofinstanceof的差別了
額,讀者:“說了這么多,你有沒有一種萬全的手段哇”。好吧, 我們來一個簡單又粗暴的鑒別手段。

var obj = 1;
Object.prototype.toString.call(obj) === '[object Number]'; //true
obj = new Number(1);
Object.prototype.toString.call(obj) === '[object Number]'; //true
obj = Symbol();
Object.prototype.toString.call(obj) === '[object Symbol]'; //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 isSymbol = function(obj) {
    return Object.prototype.toString.call(obj) == '[object Symbol]';
};
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;
};

最后再來一個好用的識別方法

function getType(p) {
    if (obj === void 0) {
        return 'Undefined';
    }
    if (obj === null) {
        return 'Null';
    }
    /function.(\w*)\(\)/.test(p.constructor); //通過其構造函數來獲取對應的類型。
    return RegExp.$1;
}
getType('1'); //"String"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM