JavaScript的知識點中,類型是易忽視的,關乎細節,你可能因之犯錯,但同時也可加以利用,要看熟悉程度。java
類型無外乎這幾種—數值(number)、字符串(string)、布爾值(boolean)、undefined、null、對象(object)。express
同時,object是廣義的對象,它又能夠包含狹義的對象、數組(array)和函數(function)。編程
先來看」檢測「。數組
方法有三種:bash
typeof最直觀,數值、字符串、布爾值分別返回number、string、boolean。app
typeof 666 // "number"
typeof '666' // "string"
typeof true // "boolean"
複製代碼
函數返回function。ide
undefined返回undefined。函數
利用這一點,typeof能夠用來檢查一個沒有聲明的變量而不報錯。實際編程中一般這麼使用ui
if (typeof v === "undefined") {
// ...
}
複製代碼
對象返回object。this
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
複製代碼
此處可印證咱們前面所說的類型,數組本質上是一種特殊的對象。
null返回object。
總結一下就是,除了數組和null檢測是object,其餘類型原樣返回。
null的類型是object,這是歷史緣由形成的。JavaScript 初版只設計了五種數據類型,沒考慮null,只把它看成object的一種特殊值,後來爲了兼容老版本就沒改變。
那麼問題來了,想知道是否是數組怎麼辦??
instanceof登場了,它是做爲一種java的運算符被引進的,可以彌補typeof有時沒法返回確切類型的缺陷,好比:
var oStringObject = new String("hello world");
typeof oStringObject;//object
oStringObject instanceof String;// true
複製代碼
固然,咱們所提的數組它也能作到
var _array = [1,2,3];
typeof _array; // object
_array instanceof Array; //true
複製代碼
這是爲何呢?來看看MDN的解釋:
instanceof 運算符用於檢測構造函數的 prototype 屬性是否出如今某個實例對象的原型鏈上。
也就是說,它可以用於檢測到原型鏈中任一環節的對象類型,你應該注意到「構造函數」這個字眼,對,除了內置對象,它還能夠檢測自定義對象。
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
mycar instanceof Car; // 返回 true
複製代碼
到此,基本應用你應該瞭解了,更多再也不細說。
能夠簡稱它toString()
,每一個對象都有一個toString()
方法,默認狀況下,toString()
方法被每一個 Object 對象繼承。若是此方法在自定義對象中未被覆蓋,toString()
返回 「[object type]」,其中 type 是對象的類型。
那麼怎麼使用呢?
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
複製代碼
爲了每一個對象都能經過 Object.prototype.toString() 來檢測,須要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式來調用,傳遞要檢查的對象做爲第一個參數。
固然,既然有未被覆蓋的狀況,就說明能夠覆蓋,好比能夠這樣覆蓋:
Object.prototype.toString = function objectToString() {
// 自定義
}
複製代碼
至此,檢測類型的方法簡單介紹完了,來看轉換。
轉換意味着變化,這個變化是運行時發生的,也是JavaScript語言的特色之一——動態類型。
某種程度上,它由於動態類型被吐槽,可能致使數據「失控」或者bug難以定位,因此近兩年TypeScript自告奮勇,本文不討論。
類型轉換一般體如今「數值、字符串、布爾值」這三種原始類型上。
主要使用Number()
、String()
和Boolean()
三個函數。
用於轉換的有這麼幾個來源:
數字——123
數字組成的字符串——「123」
數字和其餘字符相結合——「123abc」
空字符——「」
布爾值——true、false
undefined
null
複製代碼
相對來說,數值是一種格式嚴格的類型,它不該該將自己不是數字的東西轉換成數字(布爾值除外),至少目前爲止,沒有那個規則和機制,並且,Number()
是總體解析,不會去拆分,因此,以上幾個例子的結果以下:
12三、「123」——123
「123abc」、undefined——NaN
""、null、false——0
true——1
複製代碼
除此以外,還有兩個方法能夠進行數值轉換,但只對字符串有效,它們是parseInt()
、parseFloat()
,顧名思義,將字符串轉換爲整型或者浮點型數字,相比之下,它們的要求比Number()
更寬鬆。
好比:「123abc」,會轉換成 123,但也是有規則的,它不會跳躍着識別,首次碰到非數字字符後,就中止轉換,如:「123abc456」,會轉換成「123」,而「abc123」則是NaN。
Number()
方法的參數是對象時,將返回NaN,除非是包含單個數值的數組,Number([3])會轉換爲3。
相比Number()
稍顯複雜的規則,String()
溫和了不少,由於,不管是數字、字母、其餘符號仍是空格,均可做爲字符串的一部分。因而,有着下面這樣的轉換結果:
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
String([1, 2, 3]) // "1,2,3"
複製代碼
很美好,彷佛一切都是原來的模樣,僅僅是類型成爲了字符串。
固然,對象依然特殊。
String({a: 1}) // "[object Object]"
複製代碼
除此以外,還有一個toString()
方法也可用於字符串轉換,只是用法不一樣。
var order = 100;
order.toString(); //"100"
複製代碼
Boolean()函數能夠將任意類型的值轉爲布爾值。它的轉換規則相對簡單,除了如下五個值的轉換結果爲false,其餘的值所有爲true。
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
複製代碼
true和false這兩個布爾值不會發生變化。
Boolean(true) // true
Boolean(false) // false
複製代碼
對象也老實返回布爾值,但依然特殊——全部對象,包括空對象和false對應的布爾對象new Boolean(false),轉換結果均爲true。
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
複製代碼
至此,你能夠這麼理解:具有正常值(0除外)的變量類型和對象的布爾轉換都是true,其餘爲false。
隱式轉換在JS代碼中也是隨處可見,咱們可能不會寫不少顯式轉換,隱式轉換卻在自動執行着。
遇到如下三種狀況時,JavaScript 會自動轉換數據類型。
不一樣類型的數據運算
非布爾值類型求布爾值
非數值類型使用一元運算符
自動轉換的規則是:預期什麼類型的值,就調用該類型的轉換函數。
有點玄乎,下面具體介紹。
預期爲布爾值的地方,系統內部會自動調用Boolean函數將其轉換,好比很經常使用的條件判斷語句。
if ( !undefined && !null && !0 && !NaN && !'') {
console.log('true');
} // true
複製代碼
下面兩種寫法也常見,它們內部調用的也是Boolean函數。
// 寫法一
expression ? true : false
// 寫法二
!! expression
複製代碼
JavaScript 遇到預期爲字符串的地方,就會將非字符串的值自動轉爲字符串。具體規則是,先將複合類型的值轉爲原始類型的值,再將原始類型的值轉爲字符串。
字符串的自動轉換,主要發生在加法運算時。當一個值爲字符串,另外一個值爲非字符串,則後者轉爲字符串。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
複製代碼
這裏的加法我加粗了,即它體現的再也不是數學裏的「加」,而是「鏈接」,相信你們不陌生,再也不贅述。
這種自動轉換很容易出錯。
var obj = {
width: '100'
};
obj.width + 20 // "10020"
複製代碼
開發者可能指望返回120,可是因爲自動轉換,實際上返回了一個字符10020。
JavaScript 遇到預期爲數值的地方,就會將參數值自動轉換爲數值。系統內部會自動調用Number函數。
除了加法運算符(+)有可能把運算子轉爲字符串,其餘運算符都會把運算子自動轉成數值。
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1
undefined + 1 // NaN
複製代碼
上面代碼中,運算符兩側都被轉成了數值。
注意:null轉爲數值時爲0,而undefined轉爲數值時爲NaN。
一元運算符也會把運算子轉成數值。
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
複製代碼
PS:因爲自動轉換具備不肯定性,且易出錯,因此,若是你知道或者想要使用某種類型,就能夠考慮使用Boolean、Number和String函數進行顯式轉換。
至此,咱們就絮絮不休地,把看似簡單,實則不少細節的「類型」相關說完了,乍一看並不難理解,不少都很直觀,但最「煩人」的,就是那些不易察覺,也不易記憶的東西,須要咱們反覆琢磨和熟悉,才能緊緊地記住,避免出錯。
咱們很快會再見面,下一篇是什麼呢,能夠期待一下。
本文首發於我的博客:ideazhao.com/2019/10/31/…
歡迎關注~