原生JS|數據類型檢測,並沒你想象的那麼簡單

HTML5 JavaScript jQuery 文章 碼匠 2017-05-08

HTML5學堂-碼匠:看上去,JavaScript中的數據類型檢測,並沒有什麼難度,但是……它包含了不少的知識,如果你只知道一個typeof的話,那很建議你讀讀這篇文章,加強一下~

最近一個關係很不錯的朋友在跳槽,面試一家大型知名互聯網公司的時候,面試官問了一個看上去“超級”基礎的問題:如何進行數據類型的檢測啊?

原生JS|數據類型檢測,並沒你想象的那麼簡單

原生JS | 數據類型檢測,並沒你想象的那麼簡單

數據類型檢測方法

1 最為基礎的typeof

2 不可不知的instanceof

3 比instanceof更好的constructor

4 檢測值或表達式結果是否為NaN

5 易用的jQuery函數-isFunction、isArray等

6 高大上的原型方法 Object.prototype.toString

【1】typeof 基本數據類型的檢測

語法與範例

<script>

// 語法:typeof 被檢測的內容;

var num = 2;

console.log(typeof num);

</script>

基本解析

typeof是一個運算符,針對一個操作數(操作數可以是變量也可以是常量)進行運算,其返回值是一個字符串,返回值包括:"number"、"string"、"boolean"、 "undefined"、"object"、"function"。

<script>

var user;

var obj = {

user : 'HTML5學堂'

}

var h5course = function(){

console.log('碼匠');

}

console.log(typeof 123);

console.log(typeof 'html5');

console.log(typeof true);

console.log(typeof user);

console.log(typeof obj);

console.log(typeof h5course);

</script>

typeof的侷限性

typeof的問題在於:針對對象類型數據,無法進行具體細化的檢測。對於數組、正則、對象{}、null等數據,雖然均屬於對象類型,但卻各不相同,使用typeof進行檢測時,均返回object。

<script>

console.log(typeof null);

console.log(typeof {'user': 'HTML5學堂'});

console.log(typeof [4, 20]);

console.log(typeof (/\d{8}/));

</script>

【2】不可不知的instanceof

面對typeof的類型檢測缺陷,可以使用instanceof來彌補。

語法與範例

<script>

// 語法: 要檢測的內容 instanceof 類型

console.log([4,20] instanceof Array);

console.log(/\d{8}/ instanceof RegExp);

// 如上兩個返回值均為true

</script>

基本解析

instanceof,能夠用於數據類型的檢測,但是僅限於引用類型數據,無法檢測基本數據類型的值;檢測的返回值內容是布爾值。此外,會受到原型鏈的影響。

注:關於值類型與引用類型變量,如果不明白可以戳文章底部的相關文章鏈接進行查看。

instanceof的侷限性

侷限性1:不能夠檢測以“字面量”方式出現的基本數據類型;

<script>

// 侷限1 - 字面量式的基本數據類型無法檢測

var str = 'HTML5學堂';

var str2 = new String('碼匠');

console.log(str instanceof String);

// str的檢測返回false

console.log(str2 instanceof String);

// str2的檢測返回true

</script>

代碼解析:str是使用“字面量”的方式創建的字符串,而str2是使用String對象實例化的字符串。檢測str時,返回結果為false;而檢測str2時,返回結果為true。

侷限性2:會檢測該類所歸屬的原型鏈,只要在原型鏈當中能夠找到,檢測結果均為true,檢測結果有可能會出現問題。

<script>

// 範例1

var str = new String('碼匠');

console.log(str instanceof String);

console.log(str instanceof Object);

// 範例2

var box = document.getElementsByTagName('body');

console.log(box[0] instanceof HTMLBodyElement);

console.log(box[0] instanceof Node);

console.log(box[0] instanceof Object);

// 範例3

var arr = ['HTML5學堂', '碼匠'];

console.log(arr instanceof Array);

console.log(arr instanceof Object);

</script>

代碼解析:

在此處如果不是很瞭解原型鏈的童鞋,可以換個角度來理解。例如:數組(Array)隸屬於對象(Object),對於這種歸屬,檢測也是成功的。

還不理解?好,我們換一個更易懂的!人類,屬於哺乳動物,此時檢測我們是否是哺乳動物,結果會是什麼呢?

範例1中的字符串,的確屬於string類型,但是它是通過String構造函數實例化得到的,String本身是一個字符串對象,所以str也符合Object這個條件。

範例2中的body標籤本身是一個對象,細化一些說是一個“節點對象”,再細化說,是一個“body元素”,所以三種檢測均為true。範例3中的數組同理(數組屬於對象的一個分類)

【3】比instanceof更好的constructor

語法與範例

<script>

// 語法: 要檢測的內容.constructor === 類型

console.log([4, 20].constructor === Array);

console.log(/\d{8}/.constructor === RegExp);

console.log('碼匠'.constructor === String);

var num = 123;

console.log(num.constructor === Number);

// 如上幾個返回值均為true

</script>

基本解析

constructor是對象的一個屬性,不是運算符,constructor屬性指向對象的構造函數。constructor的作用與instanceof基本類似,但是它對instanceof的兩個缺陷均進行了彌補,也就是說:既能夠檢測基本數據類型,又不受到原型鏈的影響。

<script>

// 範例1

var box = document.getElementsByTagName('body');

console.log(box[0].constructor === HTMLBodyElement);

console.log(box[0].constructor === Node);

console.log(box[0].constructor === Object);

// 範例1中只有第一個返回true,後兩者均返回false

// 範例2

console.log([4, 20].constructor === Array);

console.log([4, 20].constructor === Object);

// 範例2中,Array的返回true,而Object的檢測返回false

</script>

constructor的侷限性

對於自己創建的構造函數,constructor的侷限性會比較大(當然這裡不是我們主要要討論的東西),constructor屬性是易變的,可以進行定義,所以並不能夠保證它指向相應的構造函數。但是,對於系統的各類構造函數,還是可以正常使用的,畢竟我們平日裡並不會去修改系統默認對象的constructor指向的。

<script>

function Me() {};

var demo = new Me();

console.log(demo.constructor);

// 此處檢測的結果是,constructor指向構造函數Me,但是我們卻可以人工修改指向,比如修改為Peo(如下代碼)

function Peo() {};

demo.constructor = Peo;

console.log(demo.constructor);

// 此處檢測的結果就變成了Peo

</script>

相關說明

如果希望瞭解instanceof、constructor的基本原理,需要掌握原型,瞭解構造函數的內在機制。如果在這方面積累不太夠的小夥伴,建議可以先掌握這些知識點,然後後期隨著自己知識的深入逐漸的理解實現原理。

檢測值或表達式結果是否為NaN

【4】isNaN函數

isNaN用於檢測值或表達式“轉換為數字”時,是否為NaN。可以用於輔助parseFloat()和parseInt()進行進一步的結果檢測。

<script>

console.log(isNaN(NaN));

console.log(isNaN(123+234));

console.log(isNaN('a1234'));

</script>

【5】易用的JQ函數-isArray等

jQuery當中,提供了大量的數據類型檢測方法(isArray、isFunction等等),可以檢查數據屬於哪種具體的對象類型,此處就不多談了,感興趣的查看JQ的API文檔即可。

【6】Object.prototype.toString.call()

語法與範例

<script>

console.log(Object.prototype.toString.call(123));

console.log(Object.prototype.toString.call(null));

console.log(Object.prototype.toString.call(true));

console.log(Object.prototype.toString.call('碼'));

console.log(Object.prototype.toString.call(/\d/));

console.log(Object.prototype.toString.call([4]));

// 如上的打印結果:

// [object Number]

// [object Null]

// [object Boolean]

// [object String]

// [object RegExp]

// [object Array]

</script>

基本解析

Object.prototype.toString比較常用於判斷對象值屬於哪種內置屬性,返回值類型為字符串,返回的字符串格式為:"[object 數據類型]"。由於許多引用類型都重寫了Object繼承來的toString方法,所以通常使用call/apply方法,借用Object.prototype.toString函數來判斷數據類型。

每一種數據類型所屬的類的原型上都有toString方法,例如:Number.prototype、String.prototype、Array.prototype等等。除了Object上的toString之外,其他類原型上的toString都用於將數據值轉換為字符串。

Plus

可以藉助字符串截取的方法,獲取Object.prototype.toString的結果,並進行處理,從而得到“Number”、“Null”等數據類型字符串,從而更方便進行數據類型比較/檢測。

<script>

var demo = '測試用data';

var type = Object.prototype.toString.call(demo).slice(8, -1);

console.log(type);

</script>

相關知識鏈接

值類型與引用類型變量

原生JS|數據類型檢測,並沒你想象的那麼簡單

HTML5學堂(碼匠) - https://weixin.mj216.com/

相關推薦

推薦中...