js中數據類型有8種:
基本數據類型(原始數據類型)(6種):
number, string, boolean,null, undefined, symbol(es6新增)
引用數據類型:
object, function
1. 最常用方法 -- typeof
缺點: 不能細分對象,數組,時間對象
typeof 運算符的最終結果有7種(typeof null === 'object')
"number" // typeof 123 ; typeof NaN "string" // typeof "123" "boolean" // typeof true "function" // function f() {}; typeof f "object" // typeof {}; typeof [];typeof new Date(); typeof null; typeof window "undefined" // typeof undefined; typeof 未定義變量 "symbol" // typeof Symbol();
2. 判斷對象類型--instanceof
instanceof 的原理是檢查右邊構造函數的prototype屬性是否在左邊實例對象的原型鏈上。
instanceof(a, B) {// a代表實例對象;b代表構造函數 a = a.__proto__; B = B.prototype; while(true) { if (a === null) {// 原型鏈頂層 return false; } if(a === B) { return true; } a = a.__proto__; } }
instanceof命令本質上調用的是構造函數上的靜態方法[Symbol.hasInstance]。
⚠️:原生的構造函數該方法不能被覆寫。
可以通過在自定義的構造函數上添加靜態方法[Symbol.hasInstance]自定義實現instanceof 命令。
class IsStr{ static [Symbol.hasInstance](x) { return typeof x === 'string'; } } console.log('' instanceof IsStr); //true
所以下面的實例如果 instanceof Object 全部為true
([2]) instanceof Array -> true (new Date()) instanceof Date -> true (function(){}) instanceof Function -> true ({}) instanceof Object -> true
null,undefined 使用該運算法的時候,返回值永遠是 false
三 判斷對象類型 constructor
constructor
屬性的作用是,可以得知某個實例對象,到底是哪一個構造函數產生的。
constructor屬性是prototype對象上的屬性,實例對象本身沒有這個屬性,調用的是原型對象上的constructor。
因為js規定:P.prototype.constructor === P
(new Date()).constructor === Date -> true ([2]).constructor === Array -> true (function(){}).constructor === Function -> true ({}).constructor === Object -> true
⚠️PS:instanceof 和 constructor 兩者區別:
instanceof考慮的是原型鏈
function A(){}; function B(){}; A.prototype = new B(); // 構造函數A的原型是B的實例 var aobj = new A(); console.log(aobj.constructor === B) / //true console.log(aobj.constructor === A) //false console.log(aobj instanceof A) //true console.log(aobj instanceof B) //true
類不通過prototype屬性進行原型繼承,es6的class中prototype是只讀屬性。
class A {} Object.getOwnPropertyDescriptor(A, "prototype"); /* { "value": constructor, "writable": false, "enumerable": false, "configurable": false } */
class A{}; class B{}; A.prototype = new B(); var aobj = new A(); console.log(aobj.constructor === B) //false console.log(aobj.constructor === A) //true console.log(aobj instanceof A) //true console.log(aobj instanceof B) //false
四. 通用方法
缺點: 只能判斷原生的數據類型,自定義的無法判斷。
Object.prototype.toString() 默認返回類型字符串。所有的值都繼承該方法。
但是數組、字符串、函數、Date 對象都又定義了屬於自己的toString方法,覆蓋了繼承的Object.prototype的toString()方法。
所以為了可以判斷所有的類型,統一使用Object.prototype.toString.call(value),來判斷數據類型。
call方法是用於改變this的指向,value就是方法運行時的實例對象,如果value是原始值,會自動將其轉為對應的包裝對象。
- 數值:返回
[object Number]
。 - 字符串:返回
[object String]
。 - 布爾值:返回
[object Boolean]
。 - undefined:返回
[object Undefined]
。 - null:返回
[object Null]
。 - 數組:返回
[object Array]
。 - arguments 對象:返回
[object Arguments]
。 - 函數:返回
[object Function]
。 - Error 對象:返回
[object Error]
。 - Date 對象:返回
[object Date]
。 - RegExp 對象:返回
[object RegExp]
。 - 其他對象:返回
[object Object]
。
*************判斷一個變量是否是對象的方法*************
function isObject(value) { return value === Object(value) } // 注意,原始類型的值通過Object()函數之后,會變成對應的包裝對象; // 對象(數組,對象,函數)等於本身
****************************************************