javascript 數據類型判斷 (常見庫的數據類型判斷源碼的分析)

JavaScript一共有六種數據類型,分爲原始類型(又名基本類型)和對象類型(又名引用類型)vue

原始類型有五種,分別爲number,string,boolean,undefined,null五種。git

對象類型常見的有Function,Array,Date,正則github

ES6新增Symbol瀏覽器

JavaScript 本身提供的樂行判斷

type

若是不對對象作嚴格區分使用type。angular2

number:框架

typeof 1; // "number"

string:測試

typeof 'hello world'; // "string"

boolean:prototype

typeof true; // "boolean"

undefined:code

typeof undefined; // "undefined"

null:對象

typeof null; // "undefined" (特別)

object:

typeof {};  // "object"

Symbol:

typeof Symbol(); // "symbol"

null要單獨處理,就像jQuery中同樣,若是要判斷的對象爲null,就直接返回 String(obj)

所以,能夠寫一個判斷基本類型的方法:

var type = function(obj) {
    if(obj === null) return String(obj);
    return typeof obj;
}

instanceof

instanceof 是用來明確對象爲某種特定類型的方法。

instanceof 的實現使用了原型繼承的L表示左表達式,R表示右表達式,它是用L.__proto__ 是否等於 R.prototype 來判斷對象的類型的。

String:

var str = new String('hello world');

str instanceof String // true

String:

var str = new Number('10');

str instanceof String // true

Datte:

var o = new Date();

o instanceof Date; // true

Array:

var o = new Array();

o instanceof Array; // true

RegExp:

var reg = new RegExp('/^[a-z]$/');

reg instanceof RegExp; // true

Object:

var o = new Object();

o instanceof Object; // true

var o2 = {};

o2 instanceof Object; // true

Function:

var o = function() {};

o instanceof Function; // true

Func(自定義):

function Func() {}

var o = new Func();

o instanceof Func; // true

instanceof 便可以驗證自定義對象,也能夠驗證內置對象類型,但有一點咱們要注意,那就是他們自己就是對象。

var str = new String('hello world');

str instanceof Object; // true

咱們在一開始就說明了instanceof的實現原理,知道instanceof左邊是右邊的實例,因此咱們能夠用以下代碼獲取對象的類型名:

obje.__proto__.constructor.name;

所以,咱們能夠寫一個判斷對象類型的方法以下:

objectType = function(obj) {
    if(typeof obj === 'object' || typeof obj === 'function') {
        return obj.__proto__.constructor.name;
    }
}

上面的方法雖好,可是ie瀏覽器不支持 __proto__(這個屬性也是咱們判斷瀏覽器與非瀏覽器的經常使用方式)。

下面介紹一個萬能的方法。

Object.prototype.toString.call(obj)

Object.prototype.toString.call('hello world'); // "[object String]"

Object.prototype.toString.call(1); // "[object Number]"

Object.prototype.toString.call(true); // "[object Boolean]"

Object.prototype.toString.call(null); // "[object Null]"

Object.prototype.toString.call(); // "[object Undefined]"

Object.prototype.toString.call([]); // "[object Array]"

Object.prototype.toString.call({}); // "[object Object]"

Object.prototype.toString.call(new Date()); // "[object Date]"

Object.prototype.toString.call(/test/i); // "[object RegExpArray]"

Object.prototype.toString.call(function () {}); // "[object Function]"

獲取數據類型的代碼以下:

var core_toString = Object.prototype.toString;
var getObjectType = function(obj) () {
    return core_toString.call(obj).slice(8, -1);
}

這個方法能夠判斷全部的數據類型,也是官方推薦的,可是在實際的開發中,咱們使用 typeof 來判斷基本類型,用 Objet.prototype.toString.call(obj) 判斷引用類型。

常見框架和庫的實數據類型判斷

jQuery:

var class2type = {};
var core_toString = Object.prototype.toString;

"Boolean Number String Function Array Date RegExp Object Error".split(' ').forEach(function(name, i) {
    class2type["[object " + name + "]"] = name.toLowerCase();
});

var getType = function (obj) {
    if (obj == null) {
        return String(obj);
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;
};
// 測試
getType(function(){}); // "function"
getType([]); // "array"

這裏將jQuery的實現原理抽取出來,用原生js實現。

vue.js

/**
 * 判斷是否爲基本數據類型
 */
function isPrimitive (value) {
  return (
    typeof value === 'string' ||
    typeof value === 'number' ||
    // $flow-disable-line
    typeof value === 'symbol' ||
    typeof value === 'boolean'
  )
}

/**
 * 判斷是否爲普通對象
 */
function isObject (obj) {
  return obj !== null && typeof obj === 'object'
}

/**
 * 獲取原生類型,如: [object Object]
 */
var _toString = Object.prototype.toString;

function toRawType (value) {
  return _toString.call(value).slice(8, -1)
}

/**
 * 普通對象
 */
function isPlainObject (obj) {
  return _toString.call(obj) === '[object Object]'
}
/**
 * 正則對象
 */
function isRegExp (v) {
  return _toString.call(v) === '[object RegExp]'
}

angular2:

function isPresent(obj) {
return obj !== undefined && obj !== null;
}
exports.isPresent = isPresent;
function isBlank(obj) {
return obj === undefined || obj === null;
}
exports.isBlank = isBlank;
function isBoolean(obj) {
return typeof obj === "boolean";
}
exports.isBoolean = isBoolean;
function isNumber(obj) {
return typeof obj === "number";
}
exports.isNumber = isNumber;
function isString(obj) {
return typeof obj === "string";
}
exports.isString = isString;
function isFunction(obj) {
return typeof obj === "function";
}
exports.isFunction = isFunction;
function isType(obj) {
return isFunction(obj);
}
exports.isType = isType;
function isStringMap(obj) {
return typeof obj === 'object' && obj !== null;
}
exports.isStringMap = isStringMap;
function isPromise(obj) {
return obj instanceof _global.Promise;
}
exports.isPromise = isPromise;
function isArray(obj) {
return Array.isArray(obj);
}
exports.isArray = isArray;
function isDate(obj) {
return obj instanceof exports.Date && !isNaN(obj.valueOf());
}
exports.isDate = isDate;

咱們常見的就是這幾種實現方式,或是這幾種方式的混合(zepto.js)。

JavaScript相關文章github.com

相關文章
相關標籤/搜索