JS中獲取數據類型的方法,你真的知道嗎?不一定吧

今天我們來討論一下js中獲取數據類型的各種方法。


在討論這個話題之前,我們先來看看js中的數據類型。在最新的 ECMAScript 標準中定義了 8 種數據類型:Boolean,Null,Undefined,Number,BigInt,String,Symbol 和 對象類型。


Boolean表示一個邏輯實體,可以有兩個值:true 和 false。Null 類型只有一個值:null。


Undefined 類型一個沒有被賦值的變量會有個默認值 undefined。


數字類型,根據 ECMAScript 標準,JavaScript 中只有一種數字類型:基於 IEEE 754 標準的雙精度 64 位二進制格式的值(-(253 -1) 到 253 -1)。除了能夠表示浮點數外,還有一些帶符號的值:+Infinity,-Infinity 和 NaN 。


BigInt 類型是 JavaScript 中的一個基礎的數值類型,可以用任意精度表示整數。使用 BigInt,您可以安全地存儲和操作大整數,甚至可以超過數字的安全整數限制。BigInt是通過在整數末尾附加 n 或調用構造函數來創建的。


String類型用於表示文本數據。它是一組16位的無符號整數值的“元素”。在字符串中的每個元素佔據了字符串的位置。第一個元素的索引為0,下一個是索引1,依此類推。字符串的長度是它的元素的數量。

JavaScript 字符串是不可更改的。這意味著字符串一旦被創建,就不能被修改。但是,可以基於對原始字符串的操作來創建新的字符串。


符號(Symbols)是ECMAScript 第6版新定義的。符號類型是唯一的並且是不可修改的, 並且也可以用來作為Object的key的值(如下). 在某些語言當中也有類似的原子類型(Atoms). 你也可以認為為它們是C裡面的枚舉類型。


對象類型,在 Javascript 裡,對象可以被看作是一組屬性的集合。申明的方式一般是 var obj = new Object()。


下面我們來正式看看js中四種判斷js數據類型的方法。


1、typeof

typeof 返回一個表示數據類型的字符串,返回結果包括:number、boolean、string、object、undefined、function等6種數據類型。看下面的例子:


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


typeof 可以對JS基礎數據類型做出準確的判斷,而對於引用類型返回的基本上都是object, 其實返回object也沒有錯,因為所有對象的原型鏈最終都指向了Object,Object是所有對象的`祖宗`。但當我們需要知道某個對象的具體類型時,typeof 就顯得有些力不從心了。


2、instanceof


instanceof 是用來判斷 A 是否為 B 的實例對,表達式為:A instanceof B,如果A是B的實例,則返回true,否則返回false。在這裡需要特別注意的是:instanceof檢測的是原型。


我們再來看幾個例子:


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


我們發現,雖然 instanceof 能夠判斷出 [] 是Array的實例,但它認為 [] 也是Object的實例,為什麼呢?我們來分析一下[]、Array、Object 三者之間的關係: 從instanceof 能夠判斷出 [].__proto__ 指向 Array.prototype, 而 Array.prototype.__proto__ 又指向了Object.prototype,Object.prototype.__proto__ 指向了null,標誌著原型鏈的結束。因此,[]、Array、Object就形成了如下圖所示的一條原型鏈:


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


從原型鏈可以看出,[] 的 __proto__ 直接指向Array.prototype, 間接指向Object.prototype, 所以按照 instanceof 的判斷規則,[] 就是Object的實例。當然,類似的new Date()、new Person() 也會形成這樣一條原型鏈,因此,instanceof 只能用來判斷兩個對象是否屬於原型鏈的關係, 而不能獲取對象的具體類型。


3、constructor


當一個函數F被定義時,JS引擎會為F添加prototype原型,然後再在prototype上添加一個constructor屬性,並讓其指向F的引用。如下所示:


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


當執行 var f = new F() 時,F被當成了構造函數,f是F的實例對象,此時F原型上的constructor傳遞到了f上,因此f.constructor == F


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


可以看出,JS在函數F的原型上定義了constructor,當F被當作構造函數用來創建對象時,創建的新對象就被標記為了“F” 類型,使得新對象有名有姓,可以追溯。同理,JS中的數據類型也遵守這個規則:


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


細節問題:


null和undefined是無效的對象,因此是不會有constructor存在的,這兩種類型的數據需要通過typeof來判斷。

JS對象的constructor是不穩定的,這個主要體現在自定義對象上,當開發者重寫prototype後,原有的constructor會丟失,constructor會默認為Object


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


為什麼變成了Object?prototype被重新賦值的是一個{}, {}是new Object()的字面量,因此new Object()會將Object原型上的constructor傳遞給{},也就是Object本身。因此,為了規範,在重寫對象原型時一般都需要重新給constructor賦值,以保證實例對象的類型不被改寫。


4、Object.prototype.toString


toString是Object原型對象上的一個方法,該方法默認返回其調用者的具體類型,更嚴格的講,是 toString運行時this指向的對象類型, 返回的類型格式為[object,xxx],xxx是具體的數據類型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,... 基本上所有對象的類型都可以通過這個方法獲取到。


JS中獲取數據類型的方法,你真的知道嗎?不一定吧


需要注意的是,必須通過Object.prototype.toString.call來獲取,而不能直接 new Date().toString(), 從原型鏈的角度講,所有對象的原型鏈最終都指向了Object, 按照JS變量查找規則,其他對象應該也可以直接訪問到Object的toString方法,而事實上,大部分的對象都實現了自身的toString方法,這樣就可能會導致Object的toString被終止查找,因此要用call來強制執行Object的toString方法。


分享到:


相關文章: