亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

17道題讓你徹底理解JS中的類型轉換

2019-11-19 11:03:41
字體:
來源:轉載
供稿:網友

前言

類型轉換是將值從一種類型轉換為另一種類型的過程(比如字符串轉數字,對象轉布爾值等)。任何類型不論是原始類型還是對象類型都可以進行類型轉換,JavaScript 的原始類型有:number, string, boolean, null, undefined, Symbol。

本文將通過 17 道題目來深入的了解 JS 中的類型轉換,通過閱讀本文之后,你將能自信的回答出下面題目的答案,并且能夠理解背后的原理。在文章的最后,我講寫出答案并解釋。在看答案之前,你可以把答案寫下來,最后再對照一下,便于找出理解有誤的地方。

true + false12 / "6""number" + 15 + 315 + 3 + "number"[1] > null"foo" + + "bar""true" == truefalse == "false"null == ""!!"false" == !!"true"["x"] == "x"[] + null + 1[1,2,3] == [1,2,3]{} + [] + {} + [1]! + [] + [] + ![]new Date(0) - 0new Date(0) + 0

類似于上面的這些問題大概率也會在 JS 面試中被問到, 所以繼續往下讀。

隱式 vs 顯式類型轉換

類型轉換可以分為隱式類型轉換和顯式類型轉換。

當開發人員通過編寫適當的代碼(如Number(value))用于在類型之間進行轉換時,就稱為顯式類型強制轉換(或強制類型轉換)。

然而 JavaScript 是弱類型語言,在某些操作下,值可以在兩種類型之間自動的轉換,這叫做隱式類型轉換。在對不同類型的值使用運算符時通常會發生隱式類型轉換。比如 1 == null, 2 / "5", null + new Date() 。當值被 if 語句包裹時也有可能發生,比如 if(value) {} 會將 value 轉換為 boolean類型。

嚴格相等運算符(===)不會觸發類型隱式轉換,所以它可以用來比較值和類型是否都相等。

隱式類型轉換是一把雙刃劍,使用它雖然可以寫更少的代碼但有時候會出現難以被發現的bug。

三種類型轉換

我們需要知道的第一個規則是:在 JS 中只有 3 種類型的轉換

  • to string
  • to boolean
  • to number

第二,類型轉換的邏輯在原始類型和對象類型上是不同的,但是他們都只會轉換成上面 3 種類型之一。

我們首先分析一下原始類型轉換。

String 類型轉換

String() 方法可以用來顯式將值轉為字符串,隱式轉換通常在有 + 運算符并且有一個操作數是 string 類型時被觸發,如:

String(123) // 顯式類型轉換123 + '' // 隱式類型轉換

所有原始類型轉 String 類型

String(123) // '123'String(-12.3) // '-12.3'String(null) // 'null'String(undefined) // 'undefined'String(true) // 'true'

Symbol 類型轉 String 類型是比較嚴格的,它只能被顯式的轉換

String(Symbol('symbol')) // 'Symbol(symbol)''' + Symbol('symbol') // TypeError is thrown

Boolean 類型轉換

Boolean() 方法可以用來顯式將值轉換成 boolean 型。

隱式類型轉換通常在邏輯判斷或者有邏輯運算符時被觸發(|| && !)。

Boolean(2) // 顯示類型轉換if(2) {} // 邏輯判斷觸發隱式類型轉換!!2  // 邏輯運算符觸發隱式類型轉換2 || 'hello' // 邏輯運算符觸發隱式類型轉換

注意: 邏輯運算符(比如 || 和 &&)是在內部做了 boolean 類型轉換,但實際上返回的是原始操作數的值,即使他們都不是 boolean 類型。

// 返回 number 類型 123,而不是 boolean 型 true// 'hello' 和 '123' 仍然在內部會轉換成 boolean 型來計算表達式let x = 'hello' && 123 // x === 123

boolean 類型轉換只會有 true 或者 false 兩種結果。

Boolean('')  // falseBoolean(0)  // false Boolean(-0)  // falseBoolean(NaN)  // falseBoolean(null)  // falseBoolean(undefined) // falseBoolean(false) // false

任何不在上面列表中的值都會轉換為 true, 包括 object, function, Array, Date 等,Symbol 類型是真值,空對象和空數組也是真值。

Boolean({})  // trueBoolean([])  // trueBoolean(Symbol()) // true!!Symbol()  // trueBoolean(function() {}) // true

Number 類型轉換

和 Boolean()、String() 方法一樣, Number() 方法可以用來顯式將值轉換成 number 類型。
number 的隱式類型轉換是比較復雜的,因為它可以在下面多種情況下被觸發。

  1. 比較操作(>, <, <=, >=)
  2. 按位操作(| & ^ ~)
  3. 算數操作(- + * / %), 注意,當 + 操作存在任意的操作數是 string 類型時,不會觸發 number 類型的隱式轉換
  4. 一 元 + 操作
  5. 非嚴格相等操作(== 或者 !== ),注意,== 操作兩個操作數都是 string 類型時,不會發生 number 類型的隱式轉換
Number('123') // 顯示類型轉換+ '123'  // 隱式類型轉換123 != "456" // 隱式類型轉換4 > "5" // 隱式類型轉換5 / null // 隱式類型轉換true | 0 // 隱式類型轉換

接下來看一下原始類型顯示轉換 number 類型會發生什么

Number(null)   // 0Number(undefined)  // NaNNumber(true)   // 1Number(false)   // 0Number(" 12 ")   // 12Number("-12.34")  // -12.34Number("/n")   // 0Number(" 12s ")  // NaNNumber(123)   // 123

當將一個字符串轉換為一個數字時,引擎首先刪除前尾空格、/n、/t 字符,如果被修剪的字符串不成為一個有效的數字,則返回 NaN。如果字符串為空,則返回 0。

Number() 方法對于 null 和 undefined 的處理是不同的, null 會轉換為 0, undefined 會轉換為 NaN

不管是顯式還是隱式轉換都不能將 Symbol 類型轉為 number 類型,當試圖這樣操作時,會拋出錯誤。

Number(Symbol('my symbol')) // TypeError is thrown+Symbol('123')   // TypeError is thrown

這里有 2 個特殊的規則需要記?。?/p>

1、當將 == 應用于 null 或 undefined 時,不會發生數值轉換。null 只等于 null 或  undefined,不等于其他任何值。

null == 0  // false, null is not converted to 0null == null  // trueundefined == undefined // truenull == undefined // trueundefined == 0  // false

2、NaN 不等于任何值,包括它自己

NaN === NaN // falseif(value !== value) { console.log('the value is NaN') }

object 類型轉換

到這里我們已經深入了解了原始類型的轉換,接下來我們來看一下 object 類型的轉換。

當涉及到對象的操作比如:[1] + [2,3],引擎首先會嘗試將 object 類型轉為原始類型,然后在將原始類型轉為最終需要的類型,而且仍然只有 3 種類型的轉換:number, string, boolean

最簡單的情況是 boolean 類型的轉換,任何非原始類型總是會轉換成 true,無論對象或數組是否為空。

對象通過內部 [[ToPrimitive]] 方法轉換為原始類型,該方法負責數字和字符串轉換。

[[ToPrimitive]] 方法接受兩個參數一個輸入值和一個需要轉換的類型(Numer or String)

number 和 string的轉換都使用了對象的兩個方法: valueOf 和 toString。這兩個方法都在 Object.prototype 上被聲明,因此可用于任何派生類,比如 Date, Array等。

通常上 [[ToPrimitive]] 算法如下:

  • 如果輸入的值已經是原始類型,直接返回這個值。
  • 輸入的值調用 toString() 方法,如果結果是原始類型,則返回。
  • 輸入的值調用 valueOf() 方法,如果結果是原始類型,則返回。
  • 如果上面 3 個步驟之后,轉換后的值仍然不是原始類型,則拋出 TypeError 錯誤。

number 類型的轉換首先會調用 valueOf() 方法,如果不是原始值在調用 toString() 方法。 string 類型的轉換則相反。

大多數 JS 內置對象類型的 valueOf() 返回這個對象本身,其結果經常被忽略,因為它不是一個原始類型。所以大多數情況下當 object 需要轉換成 number 或 string 類型時最終都調用了 toString() 方法。

當運算符不同時,[[ToPrimitive]] 方法接受的轉換類型參數也不相同。當存在 == 或者 + 運算符時一般會先觸發 number 類型的轉換再觸發 string 類型轉換。

在 JS 中你可以通過重寫對象的 toString 和 valueOf 方法來修改對象到原始類型轉換的邏輯。

答案解析

接下來我們按照之前的轉換邏輯來解釋一下每一道題,看一下是否和你的答案一樣。

true + false // 1

'+' 運算符會觸發 number 類型轉換對于 true 和 false

12 / '6' // 2

算數運算符會把字符串 ‘6' 轉為 number 類型

"number" + 15 + 3 // "number153"

'+' 運算符按從左到右的順序的執行,所以優先執行 “number” + 15, 把 15 轉為 string 類型,得到 “number15” 然后同理執行 “number15” + 3

15 + 3 + "number" // "18number"

15 + 3 先執行,運算符兩邊都是 number 類型 ,不用轉換,然后執行 18 + “number” 最終得到 “18number”

[1] > null // true==> '1' > 0==> 1 > 0==> true

比較運算符 > 執行 number 類型隱式轉換。

"foo" + + "bar" // "fooNaN"==> "foo" + (+"bar")==> "foo" + NaN==> "fooNaN"

一元 + 運算符比二元 + 運算符具有更高的優先級。所以 + bar表達式先求值。一元加號執行字符串“bar” 的 number 類型轉換。因為字符串不代表一個有效的數字,所以結果是NaN。在第二步中,計算表達式'foo' + NaN。

'true' == true // false==> NaN == 1==> false'false' == false // false==> NaN == 0==> false

== 運算符執行 number 類型轉換,'true' 轉換為 NaN, boolean 類型 true 轉換為 1

null == '' // false

null 不等于任何值除了 null 和 undefined

!!"false" == !!"true" // true==> true == true==> true

!! 運算符將字符串 'true' 和 'false' 轉為 boolean 類型 true, 因為不是空字符串,然后兩邊都是 boolean 型不在執行隱式轉換操作。

['x'] == 'x' // true

== 運算符對數組類型執行 number 轉換,先調用對象的 valueOf() 方法,結果是數組本身,不是原始類型值,所以執行對象的 toString() 方法,得到字符串 'x'

[] + null + 1 // 'null1'==> '' + null + 1==> 'null' + 1==> 'null1'

'+' 運算符執行 number 類型轉換,先調用對象的 valueOf() 方法,結果是數組本身,不是原始類型值,所以執行對象的 toString() 方法,得到字符串 '', 接下來執行表達式 '' + null + 1。

0 || "0" && {} // {}==> (0 || '0') && {}==> (false || true) && true==> true && true==> true

邏輯運算符 || 和 && 將值轉為 boolean 型,但是會返回原始值(不是 boolean)。

[1,2,3] == [1,2,3] // false

當運算符兩邊類型相同時,不會執行類型轉換,兩個數組的內存地址不一樣,所以返回 false

{} + [] + {} + [1] // '0[object Object]1'==> +[] + {} + [1]==> 0 + {} + [1]==> 0 + '[object Object]' + '1'==> '0[object Object]1'

所有的操作數都不是原始類型,所以會按照從左到右的順序執行 number 類型的隱式轉換, object 和 array 類型的 valueOf() 方法返回它們本身,所以直接忽略,執行 toString() 方法。 這里的技巧是,第一個 {} 不被視為 object,而是塊聲明語句,因此它被忽略。計算從 +[] 表達式開始,該表達式通過toString()方法轉換為空字符串,然后轉換為0。

! + [] + [] + ![] // 'truefalse'==> !(+[]) + [] + (![])==> !0 + [] + false==> true + [] + false==> true + '' + false==> 'truefalse'

一元運算符優先執行,+[] 轉為 number 類型 0,![] 轉為 boolean 型 false。

new Date(0) - 0 // 0==> 0 - 0==> 0

'-' 運算符執行 number 類型隱式轉換對于 Date 型的值,Date.valueOf() 返回到毫秒的時間戳。

new Date(0) + 0==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'

'+' 運算符觸發默認轉換,因此使用 toString() 方法,而不是 valueOf()。

總結

查看原文

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日韩另类| 亚洲国产日韩欧美综合久久| 国产婷婷成人久久av免费高清| 亚洲激情成人网| 亚洲深夜福利网站| 91亚洲精品在线| 欧美成人剧情片在线观看| 亚洲日本中文字幕| 91国产一区在线| 亚洲va欧美va在线观看| 国产精品一区二区女厕厕| 国产精品久久久久影院日本| 国产精品视频中文字幕91| 国产精品久久久久久av下载红粉| 亚洲色图欧美制服丝袜另类第一页| 91免费视频国产| 国产成人亚洲综合91精品| 国产女人18毛片水18精品| 另类专区欧美制服同性| 欧美成人免费一级人片100| 欧美精品一区二区三区国产精品| 国产精品毛片a∨一区二区三区|国| 亚洲一区二区三区乱码aⅴ| 精品亚洲一区二区三区在线观看| 亚洲国产99精品国自产| 97国产在线观看| 国产亚洲欧美视频| 亚洲欧洲国产伦综合| 77777亚洲午夜久久多人| 狠狠爱在线视频一区| 精品自拍视频在线观看| 国产精品wwww| 91久久国产综合久久91精品网站| 久久成人在线视频| 久久精品国产v日韩v亚洲| 成人免费午夜电影| 69av视频在线播放| 欧美资源在线观看| 正在播放国产一区| 亚洲精品国产精品国自产在线| 97成人精品视频在线观看| 亚洲国产成人久久综合一区| 久久欧美在线电影| 在线丨暗呦小u女国产精品| 欧美激情在线视频二区| 色婷婷成人综合| 亚洲精品视频久久| 欧美成人午夜免费视在线看片| 欧美在线一区二区三区四| 亚洲一区二区黄| 国产精品久久久久一区二区| 久久久精品久久久久| 青草青草久热精品视频在线观看| 国产丝袜精品视频| 欧美成人午夜激情视频| 国产精品视频免费观看www| 日本亚洲欧美成人| 久久久精品国产| 2019中文字幕全在线观看| 久久精品国产2020观看福利| 日韩精品在线第一页| 色777狠狠综合秋免鲁丝| 岛国视频午夜一区免费在线观看| 91av视频在线观看| 久久影视电视剧凤归四时歌| 亚洲欧美日韩国产中文专区| 91理论片午午论夜理片久久| 一本大道香蕉久在线播放29| 成人美女av在线直播| www.欧美视频| 国产一区二区在线免费视频| 91精品国产高清| 欧美华人在线视频| 在线观看精品自拍私拍| 久久久精品中文字幕| 国产精品久久一| 久久久久这里只有精品| 国产精品激情自拍| 国产一区二区三区久久精品| 亚洲欧洲激情在线| 国产精品夫妻激情| 亚洲天堂av在线播放| 欧美一级大片视频| 日韩中文字幕欧美| 成人免费淫片aa视频免费| 亚洲国产成人av在线| 亚洲男人第一网站| 亚洲人精选亚洲人成在线| 在线日韩中文字幕| 亚洲欧美激情在线视频| 日韩在线观看av| 亚洲人成电影网站色| 国内精品模特av私拍在线观看| 亚洲精品视频中文字幕| 国产91免费观看| 国产不卡在线观看| 欧美日韩精品在线播放| 亚洲综合小说区| 亚洲国产精品电影在线观看| 久久91精品国产91久久跳| 欧美成人在线网站| 亚洲午夜性刺激影院| 97成人精品视频在线观看| 国产成人综合精品在线| 亚洲人成毛片在线播放| 国产精品精品国产| 日韩在线中文视频| 国产精品久久久一区| 亚洲精品久久久一区二区三区| 国产玖玖精品视频| 欧美日韩国产色| 热久久视久久精品18亚洲精品| 亚洲欧美三级在线| 久久精品国产亚洲一区二区| 韩国19禁主播vip福利视频| 日韩成人在线视频观看| 国语自产精品视频在线看一大j8| 国产在线999| 国产精品综合不卡av| 欧洲成人在线视频| 亚洲视频日韩精品| 欧美日韩成人在线视频| 国产精品一区二区三区在线播放| 中文字幕亚洲欧美日韩2019| 成人在线小视频| 亚洲爱爱爱爱爱| 久久九九热免费视频| 亚洲国产日韩精品在线| 在线观看国产精品淫| 91久久在线观看| 欧美视频中文字幕在线| 亚洲香蕉av在线一区二区三区| 国产精品成人免费视频| 午夜精品视频在线| 国产日韩欧美一二三区| 欧美xxxx14xxxxx性爽| 国产日韩中文在线| 国产精品99一区| 欧美激情视频一区二区三区不卡| 久久av资源网站| 欧美日韩精品二区| 午夜精品久久久久久久久久久久| 国产欧美日韩中文| 亚洲人av在线影院| 国产欧美精品va在线观看| 97超碰色婷婷| 久久精品视频99| 欧美成人免费全部观看天天性色| 欧美国产精品va在线观看| 欧美国产日韩一区二区在线观看| 色一情一乱一区二区| 81精品国产乱码久久久久久| 久久国产精品久久久久久久久久| 亚洲男人天堂网站| 色偷偷9999www| 国产精品免费视频久久久| 亚洲一区二区中文字幕| 精品一区二区三区三区| 欧美xxxx18性欧美| 日韩精品中文字| 国产精品麻豆va在线播放| 精品激情国产视频| 中文字幕国产日韩| 日本亚洲欧美三级|