4種JavaScript數(shù)據(jù)類型判斷的方法

空值(null) 未定義(undefined) 布爾值(boolean) 數(shù)字(number) 字符串(string) 對象 (object) 符號(symbol, ES6中新增) 大整數(shù)(BigInt, ES2020 引入)
1、typeof
console.log(typeof ""); // stringconsole.log(typeof 1 ); // numberconsole.log(typeof NaN ); // numberconsole.log(typeof true); // booleanconsole.log(typeof undefined); // undefinedconsole.log(typeof function(){}); // functionconsole.log(typeof isNaN); // functionconsole.log(typeof Symbol()); // symbolconsole.log(typeof 123n); // bigintconsole.log(typeof []); // objectconsole.log(typeof {}); // objectconsole.log(typeof null); // objectconsole.log(typeof new Date()); // objectconsole.log(typeof new RegExp()); // object
2、instanceof
instanceof 是用來判斷 A 是否為 B 的實例,表達式為:A instanceof B,如果 A 是 B 的實例,則返回 true,否則返回 false。 需特別注意:instanceof 檢測的是原型
即instanceof 用來比較一個對象是否為某一個構(gòu)造函數(shù)的實例。instanceof可以準確的判斷復(fù)雜數(shù)據(jù)類型,但是不能正確判斷基本數(shù)據(jù)類型。
console.log(12 instanceof Number); // falseconsole.log('22' instanceof String); // falseconsole.log(true instanceof Boolean); // falseconsole.log(null instanceof Object); // falseconsole.log(undefined instanceof Object); // falseconsole.log(function a() {} instanceof Function); // trueconsole.log([] instanceof Array); // trueconsole.log({a: 1} instanceof Object); // trueconsole.log(new Date() instanceof Date); // true
補充:
instanceof 的原理:主要的實現(xiàn)原理就是只要右邊變量的 prototype在左邊變量的原型鏈上即可。
因此,instanceof 在查找的過程中會遍歷左邊變量的原型鏈,直到找到右邊變量的 prototype,如果存在返回true 否則返回false
function new_instance_of(leftVaule, rightVaule) {let rightProto = rightVaule.prototype; // 取右表達式的 prototype 值leftVaule = leftVaule.__proto__; // 取左表達式的__proto__值while (true) {if (leftVaule === null) {return false;}if (leftVaule === rightProto) {return true;}leftVaule = leftVaule.__proto__}}
注意:instanceof 運算時會遞歸查找leftVaule的原型鏈,即leftVaule.__proto__.__proto__.__proto__.__proto__... 直到找到了或者找到頂層為止。
一句話理解其運算規(guī)則:instanceof 檢測左側(cè)的 __proto__ 原型鏈上,是否存在右側(cè)的 prototype 原型。
3、constructor
JavaScript中,每個對象都有一個constructor屬性,可以得知某個實例對象,到底是哪一個構(gòu)造函數(shù)產(chǎn)生的, constructor屬性表示原型對象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系。
當一個函數(shù)F被定義時,JS引擎會為F添加prototype原型,然后在prototype上添加一個constructor屬性,并讓其指向F的引用,F(xiàn)利用原型對象的constructor屬性引用了自身,當F作為構(gòu)造函數(shù)創(chuàng)建對象時,原型上的constructor屬性被遺傳到了新創(chuàng)建的對象上,從原型鏈角度講,構(gòu)造函數(shù)F就是新對象的類型。這樣做的意義是,讓對象誕生以后,就具有可追溯的數(shù)據(jù)類型。
通過typeof運算符來判斷它是原始的值還是對象。如果是對象,就可以使用constructor屬性來判斷其類型。
如判斷數(shù)組的函數(shù):
function isArray(data){return typeof data == "object" && data.constructor == Array;}isArray([]) // true
注意:null 和 undefined 是沒有 constructor 存在的,這兩種類型的數(shù)據(jù)需要通過其他方式來判斷。
console.log('22'.constructor === String) // trueconsole.log(true.constructor === Boolean) // trueconsole.log([].constructor === Array) // trueconsole.log(document.constructor === HTMLDocument) // trueconsole.log(window.constructor === Window) // trueconsole.log(new Number(22).constructor === Number) // trueconsole.log(new Function().constructor === Function) // trueconsole.log(new Date().constructor === Date) // trueconsole.log(new RegExp().constructor === RegExp) // trueconsole.log(new Error().constructor === Error) // true
2、如果修改了原型對象,一般會同時修改constructor屬性,防止引用的時候出錯。所以,修改原型對象時,一般要同時修改constructor屬性的指向。
function Rectangle(width, height){this.width = width;this.height = height;this.getArea = function(){return '矩形的面積為' + (width * height);}}var rect1 = new Rectangle(40, 20);var rect2 = new Rectangle(50, 20);var rect3 = new Rectangle(60, 20);console.log(rect1.getArea());console.log(rect2.getArea());console.log(rect3.getArea());
如上代碼,每次實例化出一個對象,都會添加getArea方法,是三個對象共有且不變的,因此將getArea放在構(gòu)造函數(shù)中就會在創(chuàng)建對象時被多次添加,浪費內(nèi)存!
因此我們將getArea添加到原型對象上就減少了多次添加,實例化對象會沿著原型鏈查找到此屬性
實現(xiàn)了共享屬性:
function Rectangle(width, height){this.width = width;this.height = height;}// 直接替換原型對象,但是要記得添加上構(gòu)造函數(shù)屬性Rectangle.prototype = {constructor: Rectangle,getArea: function(){return '矩形的面積為' + (this.width * this.height);}}// 修改特性Object.defineProperties(Rectangle.prototype, {constructor: {enumerable: false,configurable: false,writable: false},getArea: {enumerable: false,configurable: false,writable: false}})var rect1 = new Rectangle(40, 20);var rect2 = new Rectangle(50, 20);var rect3 = new Rectangle(60, 20);console.log(rect1.getArea());console.log(rect2.getArea());console.log(rect3.getArea());
很多情況下,我們可以使用instanceof運算符或?qū)ο蟮腸onstructor屬性來檢測對象是否為數(shù)組。
如很多JS框架就是使用這兩種方法來判斷對象是否為數(shù)組類型。 但是檢測在跨框架(cross-frame)頁面中的數(shù)組時,會失敗。
原因就是在不同框架(iframe)中創(chuàng)建的數(shù)組不會相互共享其prototype屬性。例如:
<script>window.onload=function(){var iframe_arr=new window.frames[0].Array;console.log(iframe_arr instanceof Array); // falseconsole.log(iframe_arr.constructor == Array); // false}</script>
4、Object.prototype.toString.call()
Object.prototype.toString(o)是 Object 的原型方法,
獲取對象o的class屬性。這是一個內(nèi)部屬性,
連接字符串:[object + 結(jié)果(1)],格式為 [object Xxx] ,其中 Xxx 就是對象的類型。
對于 Object 對象,直接調(diào)用 toString() 就能返回 [object Object] 。而對于其他對象,則需要通過 call / apply 來調(diào)用才能返回正確的類型信息。
console.log(Object.prototype.toString.call(1)) // [object Number]console.log(Object.prototype.toString.call(1n)) // [object BigInt]console.log(Object.prototype.toString.call('123')) // [object String]console.log(Object.prototype.toString.call(true)) // [object Boolean]console.log(Object.prototype.toString.call(undefined)) // [object Undefined]console.log(Object.prototype.toString.call(null)) // [object Null]console.log(Object.prototype.toString.call({})) // [object Object]console.log(Object.prototype.toString.call([])) // [object Array]console.log(Object.prototype.toString.call(function a() {})) // [object Function]console.log(Object.prototype.toString.call(Symbol())) // [object Symbol]console.log(Object.prototype.toString.call(Math)) // [object Math]console.log(Object.prototype.toString.call(JSON)) // [object JSON]console.log(Object.prototype.toString.call(new Date())) // [object Date]console.log(Object.prototype.toString.call(new RegExp())) // [object RegExp]console.log(Object.prototype.toString.call(new Error)) // [object Error]console.log(Object.prototype.toString.call(window) // [object Window]console.log(Object.prototype.toString.call(document)) // [object HTMLDocument]
封裝一個準確判斷數(shù)據(jù)類型的函數(shù)
function __getType(object){return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];};
可以解決上面的跨框架問題。
<script>window.onload=function(){var iframe_arr=new window.frames[0].Array;console.log(Object.prototype.toString.call(iframe_arr))) // "[object Array]"}</script>
本文完~
學習更多技能
請點擊下方公眾號
![]()

