<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          關(guān)于 JS 類(lèi)型隱式轉(zhuǎn)換的完整總結(jié)

          共 6325字,需瀏覽 13分鐘

           ·

          2021-05-25 23:43

          作者:原罪

          來(lái)源:SegmentFault 思否社區(qū)


          不管是在技術(shù)聊天群還是論壇里,總能碰到 x + y 等于多少的問(wèn)題,比如 [] + {} == ?,如果你不了解其中的原理,那么就插不上話(huà),只能眼睜睜地等大佬解答了。

          Type

          說(shuō)到底還是JS類(lèi)型轉(zhuǎn)換的問(wèn)題,首先我們先溫習(xí)一下JS的7種內(nèi)置類(lèi)型:
          • Number
          • String
          • Boolean
          • Null
          • Undefined
          • Object
          • Symbol
          是不是感覺(jué)還有Function,畢竟能用typeof獲取到?不,函數(shù)、數(shù)組都是Object的子類(lèi)型。
          類(lèi)型分為基本類(lèi)型復(fù)合類(lèi)型兩種,除了對(duì)象,其它都是基本類(lèi)型。

          To Primitive

          發(fā)音:[?pr?m?t?v]
          結(jié)構(gòu):toPrimitive(input, preferedType = number)
          在對(duì)象的隱式轉(zhuǎn)換中,對(duì)象需要先轉(zhuǎn)成基本類(lèi)型,并按照如下順序執(zhí)行。
          1. 對(duì)象會(huì)先調(diào)用valueOf()。
          2. 如果沒(méi)有valueOf這個(gè)方法或者valueOf返回的類(lèi)型不是基本類(lèi)型,那么對(duì)象會(huì)繼續(xù)調(diào)用toString()方法。
          3. 如果沒(méi)有toString這個(gè)方法或者toString返回的類(lèi)型不是基本類(lèi)型,那么直接拋出TypeError異常。
          Uncaught TypeError: Cannot convert object to primitive value
          接著,我們看下各個(gè)對(duì)象的轉(zhuǎn)換實(shí)現(xiàn)

          ate的默認(rèn)preferedType=string,即在加法運(yùn)算中先執(zhí)行toString()。在 - | * | / | +x | -x 等運(yùn)算中,先執(zhí)行valueOf()數(shù)組的toString()可以等效為join(',')
          其中,數(shù)組toString()時(shí),遇到null, undefined都被忽略,遇到symbol直接報(bào)錯(cuò),遇到?jīng)]有toString()的對(duì)象也報(bào)錯(cuò)。
          [1, null, undefined, 2].toString() === '1,,,2';

          // Uncaught TypeError: Cannot convert a Symbol value to a string
          [1, Symbol('x')].toString()

          // Uncaught TypeError: Cannot convert object to primitive value
          [1, Object.create(null)].toString()

          To Number

          一些特殊值轉(zhuǎn)為數(shù)字的例子,等下要用到
          Number("0") === 0;
          Number("") === 0;
          Number("   ") === 0;
          Number("\n") === 0;
          Number("\t") === 0;
          Number(null) === 0;
          Number(false) === 0;

          Number(true) === 1;

          Number(undefined); // NaN
          Number("x"); // NaN

          加減法 +-

          加減法運(yùn)算中遵循了一些隱式轉(zhuǎn)換規(guī)則:

          遇到對(duì)象先執(zhí)行ToPrimitive轉(zhuǎn)換為基本類(lèi)型,然后按照基本類(lèi)型的規(guī)則處理

          ({}).toString() === "[object Object]"
          1 + {} === "1[object Object]"

          [2, 3].toString() === "2,3"
          1 + [2, 3] === "12,3"
          [1] + [2, 3] === "1,2,3"

          function test() {}
          test.toString() === "function test() {}"
          10 + test === "10function test() {}"

          加法過(guò)程中,遇到字符串,則會(huì)被處理為字符串拼接

          上面的對(duì)象最后也都轉(zhuǎn)成了字符串,遵循本條規(guī)則。接著來(lái)幾個(gè)純字符串的例子
          1 + "1" === "11"
          1 + 1 === 2
          "1" + 1 === "11"
          "1" + "1" === "11"
          減法操作時(shí),一律需要把類(lèi)型轉(zhuǎn)換為Number,進(jìn)行數(shù)學(xué)運(yùn)算
          3 - 1 === 2
          3 - '1' === 2
          '3' - 1 === 2

          // [].toString() => "" => Number(...) => 0
          3 - [] === 3

          // {}.toString() => "[object Object]" => Number(...) => NaN
          3 - {} // NaN

          加法操作時(shí),遇到非字符串的基本類(lèi)型,都會(huì)轉(zhuǎn)Number

          1 + true === 2
          1 + false === 1
          1 + null === 1
          1 + undefined // NaN

          + x 和 一元運(yùn)算 +x 是等效的(以及- x),都會(huì)強(qiáng)制轉(zhuǎn)換成Number

          + 0 === 0
          - 0 === -0
          1 + + "1" === 2
          1 + + + + ["1"] === 2
          // 負(fù)負(fù)得正
          1 + - + - [1] === 2
          // 負(fù)負(fù)得正
          1 - + - + 1 === 2
          1 - + - + - 1 === 0

          1 + + [""] === 1

          // ["1""2"].toString() => "1,2" => Number(...) => NaN
          1 + + ["1""2"] // NaN

          // 吃根香蕉??
          ("ba" + + undefined + "a").toLowerCase() === "banana"
          回到一開(kāi)始拋出的問(wèn)題[] + {},這樣太簡(jiǎn)單了吧?
          [].toString() === "";
          {}.toString() === "[object Object]";

          [] + {} === "[object Object]";

          對(duì)象字面量{}在最前面則不代表對(duì)象

          不是對(duì)象是什么?是你的八塊腹?。縿e急,看看經(jīng)典的例子
          {} + [] === 0;
          { a: 2 } + [] === 0;
          這啥玩意?說(shuō)好的"[object Object]"呢?
          好吧,這是{}其實(shí)代表的是代碼塊,最后就變成了+ [],根據(jù)前面的原則,數(shù)組先被轉(zhuǎn)換成字符串"",接著因?yàn)?x的運(yùn)算,字符串被轉(zhuǎn)成數(shù)字0。
          那 { a: 2 } 總該是對(duì)象了吧?其實(shí)這時(shí)候a不是代表對(duì)象屬性,而是被當(dāng)成了標(biāo)簽(label),標(biāo)簽這東西IE6就已經(jīng)有了。所以如果我們寫(xiě)成 { a: 2, b: 3 } + [] 這樣是會(huì)報(bào)錯(cuò)的,逗號(hào)要改成分號(hào)才能通過(guò)編譯。

          symbol不能加減

          如果在表達(dá)式中有symbol類(lèi)型,那么就會(huì)直接報(bào)錯(cuò)。比如1 + Symbol("x")報(bào)錯(cuò)如下:
          Uncaught TypeError: Cannot convert a Symbol value to a number

          寬松相等 ==

          相等于全等都需要對(duì)類(lèi)型進(jìn)行判斷,當(dāng)類(lèi)型不一致時(shí),寬松相等會(huì)觸發(fā)隱式轉(zhuǎn)換。下面介紹規(guī)則:

          對(duì)象與對(duì)象類(lèi)型一致,不做轉(zhuǎn)換

          {} != {}
          [] != {}
          [] != []

          對(duì)象與基本類(lèi)型,對(duì)象先執(zhí)行ToPrimitive轉(zhuǎn)換為基本類(lèi)型

          // 小心代碼塊
          "[object Object]" == {}
          [] == ""
          [1] == "1"
          [1,2] == "1,2"

          數(shù)字與字符串類(lèi)型對(duì)比時(shí),字符串總是轉(zhuǎn)換成數(shù)字

          "2" == 2
          [] == 0
          [1] == 1
          // [1,2].toString() => "1,2" => Number(...) => NaN
          [1,2] != 1

          布爾值先轉(zhuǎn)換成數(shù)字,再按數(shù)字規(guī)則操作

          // [] => "" => Number(...) => 0
          // false => 0
          [] == false

          // [1] => "1" => 1
          // true => 1
          [1] == true

          // [1,2] => "1,2" => NaN
          // true => 1
          [1,2] != true

          "0" == false
          "" == false

          null、undefined、symbol

          null、undefined與任何非自身的值對(duì)比結(jié)果都是false,但是null == undefined 是一個(gè)特例。
          null == null
          undefined == undefined
          null == undefined

          null != 0
          null != false

          undefined != 0
          undefined != false

          Symbol('x') != Symbol('x')

          對(duì)比 < >

          對(duì)比不像相等,可以嚴(yán)格相等(===)防止類(lèi)型轉(zhuǎn)換,對(duì)比一定會(huì)存在隱式類(lèi)型轉(zhuǎn)換。

          對(duì)象總是先執(zhí)行ToPrimitive為基本類(lèi)型

          [] < [] // false
          [] <= {} // true

          {} < {} // false
          {} <= {} // true

          任何一邊出現(xiàn)非字符串的值,則一律轉(zhuǎn)換成數(shù)字做對(duì)比

          // ["06"] => "06" => 6
          ["06"] < 2   // false 

          ["06"] < "2" // true
          ["06"] > 2   // true

          5 > null     // true
          -1 < null    // true
          0 <= null    // true

          0 <= false   // true
          0 < false    // false

          // undefined => Number(...) => NaN
          5 > undefined // false


          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開(kāi)更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  九九色视频 | 亚洲视频黄| 大香蕉伊人精品 | 亚洲激情一区二区三区 | 人人干人人的 |