国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

17道面試題徹底理解 JavaScript 中的類型轉換

SKYZACK / 3699人閱讀

摘要:隱式類型轉換通常在邏輯判斷或者有邏輯運算符時被觸發。一元加號執行字符串的類型轉換。邏輯運算符和將值轉為型,但是會返回原始值不是。計算從表達式開始,該表達式通過方法轉換為空字符串,然后轉換為。總結查看原文關注每日一道面試題詳解

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

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

true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
"true" == true
false == "false"
null == ""
!!"false" == !!"true"
["x"] == "x"
[] + null + 1
[1,2,3] == [1,2,3]
{} + [] + {} + [1]
! + [] + [] + ![]
new Date(0) - 0
new 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("")           // false
Boolean(0)            // false  
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)     // false
Boolean(false)        // false

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

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true
Number 類型轉換

和 Boolean()、String() 方法一樣, Number() 方法可以用來顯式將值轉換成 number 類型。

number 的隱式類型轉換是比較復雜的,因為它可以在下面多種情況下被觸發。

比較操作(>, <, <=, >=)

按位操作(| & ^ ~)

算數操作(- + * / %), 注意,當 + 操作存在任意的操作數是 string 類型時,不會觸發 number 類型的隱式轉換

一 元 + 操作

非嚴格相等操作(== 或者 !== ),注意,== 操作兩個操作數都是 string 類型時,不會發生 number 類型的隱式轉換

Number("123")    // 顯示類型轉換
+ "123"          //  隱式類型轉換
123 != "456"    //  隱式類型轉換
4 > "5"        //  隱式類型轉換
5 / null      //  隱式類型轉換
true | 0      //  隱式類型轉換

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

Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("
")                   // 0
Number(" 12s ")                // NaN
Number(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 個特殊的規則需要記住:

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

null == 0               // false, null is not converted to 0
null == null            // true
undefined == undefined  // true
null == undefined       // true
undefined == 0          // false

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

NaN === NaN  // false

if(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()。

總結

查看原文

關注github每日一道面試題詳解

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106471.html

相關文章

  • 面試寶典

    摘要:有談談面試與面試題對于前端面試的一些看法。動態規劃算法的思想及實現方法幫大家理清動態規劃的解決思路以及原理方法前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。極客學院前端練習題道練習題,面試季練練手。 由數據綁定和排序引入的幾個 JavaScript 知識點 在 JavaScript 的數據綁定和做簡單的表格排序中遇到的幾個知識點 [[JS 基礎...

    neu 評論0 收藏0
  • 面試引發的思考 --- Event Loop

    摘要:想必面試題刷的多的同學對下面這道題目不陌生,能夠立即回答出輸出個,可是你真的懂為什么嗎為什么是輸出為什么是輸出個這兩個問題在我腦邊縈繞。同步任務都好理解,一個執行完執行下一個。本文只是我對這道面試題的一點思考,有誤的地方望批評指正。 想必面試題刷的多的同學對下面這道題目不陌生,能夠立即回答出輸出10個10,可是你真的懂為什么嗎?為什么是輸出10?為什么是輸出10個10?這兩個問題在我腦...

    betacat 評論0 收藏0
  • 前端最強面經匯總

    摘要:獲取的對象范圍方法獲取的是最終應用在元素上的所有屬性對象即使沒有代碼,也會把默認的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據我測試不同環境結果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續更新中……,可以關注下github 項目地址 https:...

    wangjuntytl 評論0 收藏0
  • Python 爬蟲面試 170 :2019 版

    摘要:下面代碼會存在什么問題,如何改進一行代碼輸出之間的所有偶數。簡述進程之間如何通信多路復用的作用模型的區別什么是并發和并行解釋什么是異步非阻塞的作用面試題說說你知道的命令如何查看某次提交修改的內容答案掃碼下面的二維碼訂閱即可獲取。 引言 最近在刷面試題,所以需要看大量的 Python 相關的面試題,從大量的題目中總結了很多的知識,同時也對一些題目進行拓展了,但是在看了網上的大部分面試題不...

    trigkit4 評論0 收藏0
  • JavaScript中的算法(附10面試常見算法解決方法和思路)

    摘要:中的算法附道面試常見算法題解決方法和思路關注每日一道面試題詳解面試過程通常從最初的電話面試開始,然后是現場面試,檢查編程技能和文化契合度。值得記住的數組方法有和。一個好的解決方案是使用內置的方法。 JavaScript中的算法(附10道面試常見算法題解決方法和思路) 關注github每日一道面試題詳解 Introduction 面試過程通常從最初的電話面試開始,然后是現場面試,檢查編程...

    Cruise_Chan 評論0 收藏0

發表評論

0條評論

SKYZACK

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<