JavaScript數據類型判斷的四種方法
- 2021 年 2 月 19 日
- 筆記
- javascript
碼文不易啊,轉載請帶上本文鏈接呀,感謝感謝 //www.cnblogs.com/echoyya/p/14416375.html
本文分享了JavaScript類型判斷的四種方法:typeof
、instanceof
、Object.prototype.toString.call()
、constructor
JavaScript數據類型
JavaScript有八種內置類型,除對象外,其他統稱為基本類型
-
空值(null)
-
未定義(undefined)
-
布爾值(boolean)
-
數字(number)
-
字元串(string)
-
對象 (object)
-
符號(symbol, ES6中新增)
-
大整數(BigInt, ES2020 引入)
Symbol: 是ES6中引入的一種原始數據類型,表示獨一無二的值。
BigInt:是 ES2020 引入的一種新的數據類型,用來解決 JavaScript中數字只能到 53 個二進位位(JavaScript 所有數字都保存成 64 位浮點數,大於這個範圍的整數,無法精確表示的問題。具體可查看:新數據類型 — BigInt
一、typeof
typeof是一個操作符
而不是函數,其右側跟一個一元表達式,並返回這個表達式的數據類型。返回的結果用該類型的字元串(全小寫字母)形式表示
包括以下 8 種:string、number、boolean、undefined、function 、symbol、bigInt、object。
對於數組,對象,null以及時間等數據,typeof只能返回object,而不能直接返回對應的類型,還需要通過其他法判斷。
console.log(typeof ""); // string
console.log(typeof 1 ); // number
console.log(typeof NaN ); // number
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof function(){}); // function
console.log(typeof isNaN); // function
console.log(typeof Symbol()); // symbol
console.log(typeof 123n); // bigint
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object
console.log(typeof new Date()); // object
console.log(typeof new RegExp()); // object
二、instanceof
instanceof 是用來判斷 A 是否為 B 的實例
,表達式為:A instanceof B
,如果 A 是 B 的實例,則返回 true,否則返回 false。 需特別注意:instanceof 檢測的是原型
即instanceof 用來比較一個對象是否為某一個構造函數的實例。instanceof可以準確的判斷複雜數據類型,但是不能正確判斷基本數據類型
console.log(12 instanceof Number); // false
console.log('22' instanceof String); // false
console.log(true instanceof Boolean); // false
console.log(null instanceof Object); // false
console.log(undefined instanceof Object); // false
console.log(function a() {} instanceof Function); // true
console.log([] instanceof Array); // true
console.log({a: 1} instanceof Object); // true
console.log(new Date() instanceof Date); // true
三、constructor
- JavaScript中,每個對象都有一個constructor屬性,可以得知某個實例對象,到底是哪一個構造函數產生的, constructor屬性表示原型對象與構造函數之間的關聯關係。
-
當一個函數F被定義時,JS引擎會為F添加prototype原型,然後在prototype上添加一個constructor屬性,並讓其指向F的引用,F利用原型對象的constructor屬性引用了自身,當F作為構造函數創建對象時,原型上的constructor屬性被遺傳到了新創建的對象上,從原型鏈角度講,構造函數F就是新對象的類型。這樣做的意義是,讓對象誕生以後,就具有可追溯的數據類型。
-
通過typeof運算符來判斷它是原始的值還是對象。如果是對象,就可以使用constructor屬性來判斷其類型。
-
如判斷數組的函數:
function isArray(data){
return typeof data == "object" && data.constructor == Array;
}
isArray([]) // true
注意:null 和 undefined 是沒有 constructor 存在的,這兩種類型的數據需要通過其他方式來判斷。
console.log('22'.constructor === String) // true
console.log(true.constructor === Boolean) // true
console.log([].constructor === Array) // true
console.log(document.constructor === HTMLDocument) // true
console.log(window.constructor === Window) // true
console.log(new Number(22).constructor === Number) // true
console.log(new Function().constructor === Function) // true
console.log(new Date().constructor === Date) // true
console.log(new RegExp().constructor === RegExp) // true
console.log(new Error().constructor === Error) // true
- 如果修改了原型對象,一般會同時修改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放在構造函數中就會在創建對象時被多次添加,浪費記憶體!
-
因此我們將getArea添加到原型對象上就減少了多次添加,實例化對象會沿著原型鏈查找到此屬性
-
實現了共享屬性:
function Rectangle(width, height){
this.width = width;
this.height = height;
}
// 直接替換原型對象,但是要記得添加上構造函數屬性
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運算符或對象的constructor屬性來檢測對象是否為數組。如很多JS框架就是使用這兩種方法來判斷對象是否為數組類型。 但是檢測在跨框架(cross-frame)頁面中的數組時,會失敗。原因就是在不同框架(iframe)中創建的數組不會相互共享其prototype屬性。例如:
<script>
window.onload=function(){
var iframe_arr=new window.frames[0].Array;
console.log(iframe_arr instanceof Array); // false
console.log(iframe_arr.constructor == Array); // false
}
</script>
四、Object.prototype.toString.call()
-
Object.prototype.toString(o)
是 Object 的原型方法,-
獲取對象o的class屬性。這是一個內部屬性,
-
連接字元串:[object + 結果(1)],格式為 [object Xxx] ,其中 Xxx 就是對象的類型。
-
-
對於 Object 對象,直接調用 toString() 就能返回 [object Object] 。而對於其他對象,則需要通過 call / apply 來調用才能返回正確的類型資訊。
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]
- 封裝一個準確判斷數據類型的函數
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>