成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JavaScript 類型轉(zhuǎn)換

sydMobile / 597人閱讀

摘要:這樣導(dǎo)致結(jié)果不一致,等解析語句為,對(duì)空對(duì)象強(qiáng)制轉(zhuǎn)為數(shù)字類型,即為,將非空字符串轉(zhuǎn)換為數(shù)字類型,結(jié)果為。綜上,右邊表達(dá)式轉(zhuǎn)換為。

首先從一系列讓JavaScript初學(xué)者抓狂的運(yùn)算說起。

1 + {}
{} + 1
[] + {}
{} + []
[] + []
{} + {}

能全部答對(duì)上面的運(yùn)算結(jié)果,不必浪費(fèi)時(shí)間繼續(xù)閱讀本文了。
如果對(duì)某一些的結(jié)果還不確定,請(qǐng)慢慢往下看。

上面列的所有運(yùn)算,需要理清以下兩點(diǎn):

+{}的解析規(guī)則;

JavaScript是如何進(jìn)行類型轉(zhuǎn)換的;

+{}的解析規(guī)則 +符號(hào)

數(shù)字的加法運(yùn)算,二元運(yùn)算符

字符串的連接運(yùn)算,二元運(yùn)算符

正號(hào),一元運(yùn)算符,強(qiáng)制轉(zhuǎn)換其他類型的運(yùn)算元為數(shù)字類型

{}符號(hào)

對(duì)象的字面量

區(qū)塊語句

加法運(yùn)算規(guī)則

首先,我們來了解,+符號(hào)作為加號(hào)二元運(yùn)算符的運(yùn)算規(guī)則

使用ToPrimitive轉(zhuǎn)換左右運(yùn)算元為原始數(shù)據(jù)類型值;

在第1步轉(zhuǎn)換后,如果有運(yùn)算元出現(xiàn)原始數(shù)據(jù)類型為“字符串”類型時(shí),則另一運(yùn)算元強(qiáng)制轉(zhuǎn)換為字符串,然后做字符串連接運(yùn)算;

其他情況時(shí),所有運(yùn)算元都轉(zhuǎn)換為原始數(shù)據(jù)類型為“數(shù)字”類型,然后做數(shù)字相加運(yùn)算;

ToPrimitive運(yùn)算

從上圖總結(jié)ToPrimitive運(yùn)算的語法說明:

ToPrimitive(input, PreferredType?)

input代表代入的值,而PreferredType可以是數(shù)字(Number)或字符串(String)其中一種,這會(huì)代表“優(yōu)先的”、“首選的”的要進(jìn)行轉(zhuǎn)換到哪一種原始類型,轉(zhuǎn)換的步驟會(huì)依這里的值而有所不同。
但如果沒有提供這個(gè)值也就是預(yù)設(shè)情況,則會(huì)設(shè)置轉(zhuǎn)換的hint值為default。這個(gè)首選的轉(zhuǎn)換原始類型的指示(hint值),是在作內(nèi)部轉(zhuǎn)換時(shí)由JS視情況自動(dòng)加上的,一般情況就是預(yù)設(shè)值。

當(dāng)PreferredType為數(shù)字(Number)時(shí)

轉(zhuǎn)換步驟為:

如果input是原始數(shù)據(jù)類型,則直接返回input。

否則,如果input是個(gè)對(duì)象時(shí),則調(diào)用對(duì)象的valueOf()方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個(gè)值。

否則,如果input是個(gè)對(duì)象時(shí),調(diào)用對(duì)象的toString()方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個(gè)值。

否則,拋出TypeError錯(cuò)誤。

當(dāng)PreferredType為字符串(String)時(shí)

上面的步驟2與3對(duì)調(diào),轉(zhuǎn)換步驟為:

如果input是原始數(shù)據(jù)類型,則直接返回input。

否則,如果input是個(gè)對(duì)象時(shí),則調(diào)用對(duì)象的toString方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個(gè)值。

否則,如果input是個(gè)對(duì)象時(shí),調(diào)用對(duì)象的valueOf()方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個(gè)值。

否則,拋出TypeError錯(cuò)誤。

有幾點(diǎn)值得注意:

數(shù)字是預(yù)設(shè)的PreferredType

在一般情況下,加號(hào)運(yùn)算中的對(duì)象要作轉(zhuǎn)型時(shí),都是先調(diào)用valueOf再調(diào)用toString;

例外:Date 對(duì)象、Symbol 對(duì)象

Date 對(duì)象的預(yù)設(shè)首選類型是字符串(String);

Symbol 能顯示轉(zhuǎn)為字符串 String(Symbol) 和布爾值,不能轉(zhuǎn)為數(shù)字;

模擬代碼
a + b:
    pa = ToPrimitive(a)
    pb = ToPrimitive(b)

    if(pa is string || pb is string)
       return concat(ToString(pa), ToString(pb))
    else
       return add(ToNumber(pa), ToNumber(pb))
V8實(shí)現(xiàn)源碼
// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
// (1) for number hint, and (2) for string hint.
function ToPrimitive(x, hint) {
    if (!IS_SPEC_OBJECT(x)) return x;
    if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
    return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
}

可以看出,Date類型的對(duì)象預(yù)設(shè)值為字符串(String)。

DefaultNumberDefaultString方法

// ECMA-262, section 8.6.2.6, page 28.
function DefaultString(x) {
   if (!IS_SYMBOL_WRAPPER(x)) {
       if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
       var toString = x.toString;
       if (IS_SPEC_FUNCTION(toString)) {
           var s = % _CallFunction(x, toString);
           if (IsPrimitive(s)) return s;
       }

       var valueOf = x.valueOf;
       if (IS_SPEC_FUNCTION(valueOf)) {
           var v = % _CallFunction(x, valueOf);
           if (IsPrimitive(v)) return v;
       }
   }
   throw MakeTypeError(kCannotConvertToPrimitive);
}
// ECMA-262, section 8.6.2.6, page 28.
function DefaultNumber(x) {
    var valueOf = x.valueOf;
    if (IS_SPEC_FUNCTION(valueOf)) {
        var v = % _CallFunction(x, valueOf);
        if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
        if (IS_SIMD_VALUE(x)) throw MakeTypeError(kSimdToNumber);
        if (IsPrimitive(v)) return v;
    }
    var toString = x.toString;
    if (IS_SPEC_FUNCTION(toString)) {
        var s = % _CallFunction(x, toString);
        if (IsPrimitive(s)) return s;
    }
    throw MakeTypeError(kCannotConvertToPrimitive);
}

至此,我們弄清楚了ToPrimitive內(nèi)部運(yùn)算規(guī)則。

原始數(shù)據(jù)類型轉(zhuǎn)換規(guī)則表

對(duì)于原始數(shù)據(jù)類型直接的轉(zhuǎn)換規(guī)則就不一一解釋了,可以參看下表:

運(yùn)算例子解析 1 + {}

解析為數(shù)字1與空對(duì)象{}進(jìn)行加運(yùn)算,按照上面的規(guī)則,空對(duì)象{}按照valueOf -> toString順序,valueOf返回對(duì)象本身,所以調(diào)用toString返回"[object Object]"為字符串,根據(jù)規(guī)則,有一個(gè)為字符串,則進(jìn)行字符串連接運(yùn)算,數(shù)字1強(qiáng)制轉(zhuǎn)換為字符串"1",最終結(jié)果為"1[object Object]"。

{} + 1

這個(gè)例子有坑,因?yàn)閷?duì)于瀏覽器引擎來說,它們會(huì)認(rèn)為以花括號(hào)開頭{的,是一個(gè) 區(qū)塊語句 的開頭,而不是一個(gè)對(duì)象字面量的語句,所以會(huì)認(rèn)為略過第一個(gè){}。所以這個(gè)例子相當(dāng)于+1,加號(hào)運(yùn)算會(huì)直接變?yōu)橐辉?hào)運(yùn)算,對(duì)數(shù)字1強(qiáng)制轉(zhuǎn)換為數(shù)字類型,結(jié)果為1。

[] + {}

[]{}分別調(diào)用ToPrimitive方法,返回"""[object Object]",然后做字符串拼接得到"[object Object]"。

{} + []

開始的{}被解析為區(qū)塊語句而略過,相當(dāng)于+[],而[]轉(zhuǎn)為原始數(shù)據(jù)類型結(jié)果為"",強(qiáng)制轉(zhuǎn)換""為數(shù)字類型,結(jié)果為0;

[] + []

[]{}分別調(diào)用ToPrimitive方法,返回"""",然后做字符串拼接得到""。

{} + {}

這個(gè)例子有爭(zhēng)議,對(duì)于FirefoxEdge瀏覽器來說,他們一以貫之的將第一個(gè){}作為區(qū)塊語句略過,而對(duì)于V8引擎系列(ChromeNode.js等)則將第一個(gè){}解析為對(duì)象字面量。
這樣導(dǎo)致結(jié)果不一致,Firefox等解析語句為+{},對(duì)空對(duì)象{}強(qiáng)制轉(zhuǎn)為數(shù)字類型,即為+"[object Object]",將非空字符串轉(zhuǎn)換為數(shù)字類型,結(jié)果為NaN。
Chrome等解析語句為兩個(gè)空對(duì)象做加運(yùn)算,結(jié)果也比較好理解:"[object Object][object Object]"。

復(fù)雜一點(diǎn)的例子 [] == ![]

這是一個(gè)不嚴(yán)格等于運(yùn)算,我們來看轉(zhuǎn)換過程。

// 第一步,轉(zhuǎn)換右邊,根據(jù)上述原始數(shù)據(jù)類型轉(zhuǎn)換規(guī)則表,
// 所有對(duì)象強(qiáng)制轉(zhuǎn) Boolean 類型都是 true,所以 ![] 為 false
ToPrimitive(![]) >> ToPrimitive(!ToBoolean([])) >>
ToPrimitive(!true) >> ToPrimitive(false) >> 0
// 第二步,轉(zhuǎn)換左邊
ToPrimitive([]) >> ""
// 第三步,判斷
"" == 0 >> ToNumber("") == 0 >> 0 == 0 >> return true
++[[]][+[]] + [+[]]

進(jìn)一步,來看這個(gè)例子。
很明顯,根據(jù)運(yùn)算符優(yōu)先級(jí),這個(gè)表達(dá)式可以用+分隔為左右兩個(gè)部分++[[]][+[]][+[]]。

先看右邊[+[]]

可以看出這是一個(gè)數(shù)組里面有一個(gè)元素+[],而+[]即將[]強(qiáng)制轉(zhuǎn)換為數(shù)字類型,所以等于+"",結(jié)果為0
綜上,右邊表達(dá)式轉(zhuǎn)換為[0]。

再看左邊++[[]][+[]]

我們來一步步拆解, 根據(jù)對(duì)右邊表達(dá)式的轉(zhuǎn)換,這個(gè)表達(dá)式可以等同看做++([[]][0]),++后面又可以看做數(shù)組去第1個(gè)元素,表達(dá)式轉(zhuǎn)換為++[]。
但是當(dāng)我們?nèi)g覽器執(zhí)行++[]時(shí),報(bào)錯(cuò)了:Uncaught ReferenceError: Invalid left-hand side expression in prefix operation。
嚇得我趕緊去看++的語法,原來++的運(yùn)算是一種引用運(yùn)算,即++[]應(yīng)該轉(zhuǎn)換為:

var ref = []
ref = ref + 1

所以++[]轉(zhuǎn)換的正確姿勢(shì)為[] + 1

加法運(yùn)算

左右進(jìn)行相加得到:[] + 1 + [0]。
根據(jù)ToPrimitive運(yùn)算規(guī)則,[] + 1 + [0] === "" + 1 + [0] === "1" + [0] === "10"

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108893.html

相關(guān)文章

  • JavaScript隱式類型轉(zhuǎn)換

    摘要:所謂裝箱轉(zhuǎn)換,正是把基本類型轉(zhuǎn)換為對(duì)應(yīng)的對(duì)象,他是類型轉(zhuǎn)換中一種相當(dāng)重要的種類。拆箱轉(zhuǎn)換在標(biāo)準(zhǔn)中,規(guī)定了函數(shù),它是對(duì)象類型到基本類型的轉(zhuǎn)換即,拆箱轉(zhuǎn)換。拆箱轉(zhuǎn)換會(huì)嘗試調(diào)用和來獲得拆箱后的基本類型。 JavaScript隱式類型轉(zhuǎn)換 基本數(shù)據(jù)類型 ECMAScript 一共定義了七種 build-in types,其中六種為 Primitive Value,Null, Undefined...

    bingo 評(píng)論0 收藏0
  • 數(shù)據(jù)類型 - Javascript語法基礎(chǔ) - Javascript核心

    摘要:在編程語言中,能夠表示并操作的值的類型稱做數(shù)據(jù)類型。中的原始類型包括數(shù)字,字符串和布爾值。日期與時(shí)間語言核心包括構(gòu)造函數(shù),用來創(chuàng)建表示日期和時(shí)間的對(duì)象。其規(guī)則為如果是布爾值,和分別被轉(zhuǎn)換為和如果是數(shù)字值,返回本身。 源代碼: https://github.com/RobinQu/Programing-In-Javascript/blob/master/chapters/Javas...

    sevi_stuo 評(píng)論0 收藏0
  • JavaScript 中的強(qiáng)制類型轉(zhuǎn)換

    摘要:完整清單是中添加,此處不予介紹布爾值用來表示可能是真或假的值。結(jié)果抽象比較運(yùn)算符在比較它們之前在類型之間進(jìn)行自動(dòng)轉(zhuǎn)換。中的隱式轉(zhuǎn)換稱為強(qiáng)制類型轉(zhuǎn)換,并在規(guī)范中定義。這些內(nèi)置類型可用于在不同類型之間進(jìn)行顯式轉(zhuǎn)換。 翻譯:瘋狂的技術(shù)宅原文:https://www.valentinog.com/bl... 本文首發(fā)微信公眾號(hào):前端先鋒歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 show...

    endiat 評(píng)論0 收藏0
  • JavaScript核心語法——數(shù)據(jù)類型

    摘要:原始類型分別有類型類型和類型三種。類型中存在一個(gè)特殊的值叫。也可以把其他類型的數(shù)據(jù)自動(dòng)轉(zhuǎn)換為類型運(yùn)算符運(yùn)算符判斷原始類型語法結(jié)構(gòu)變量名稱。 數(shù)據(jù)類型 1.數(shù)據(jù)類型的概述;在JavaScript代碼中,能夠表示并且操作值的類型就叫做數(shù)據(jù)類型數(shù)據(jù)類型可以分成可變類型和不可變類型,可變類型的值是可以修改的。相反不可變類型的值是不可以修改的。數(shù)據(jù)類型還有原始類型(原始值)與引用類型(內(nèi)置對(duì)象)...

    wfc_666 評(píng)論0 收藏0
  • Front-end developmenter必看,超實(shí)用的javaScript隱式類型轉(zhuǎn)換規(guī)則記憶

    摘要:下面先看看涉及到的幾個(gè)函數(shù)以及他們的轉(zhuǎn)換規(guī)則,這個(gè)是需要記憶的內(nèi)容類型轉(zhuǎn)換需要使用到的函數(shù)對(duì)于布爾值用到的是對(duì)于數(shù)值,用到的是當(dāng)然還有但是對(duì)于隱式類型轉(zhuǎn)換的時(shí)候,調(diào)用的是前者。 javaScript類型轉(zhuǎn)換規(guī)則 javaScript的類型轉(zhuǎn)換其實(shí)一直是很多前端開發(fā)人員很迷的地方,一會(huì)兒這里要轉(zhuǎn)換,一會(huì)兒那里又要轉(zhuǎn)換,總之就是一個(gè)大寫的迷,因?yàn)樗[式類型轉(zhuǎn)換的地方實(shí)在是太多了。 但其實(shí)...

    fuchenxuan 評(píng)論0 收藏0
  • JavaScript類型轉(zhuǎn)換的迷糊事兒

    摘要:下面分幾步來簡單的探探不同類型的轉(zhuǎn)換吧以下的內(nèi)容,都可以從權(quán)威指南中找到。其他值轉(zhuǎn)換成在編寫代碼的過程中,幾乎不用考慮它的取值類型。核心內(nèi)置類,會(huì)嘗試先于可以理解為對(duì)象優(yōu)先轉(zhuǎn)換成數(shù)字例外的是,利用的是轉(zhuǎn)換。 最近在寫公司的登錄注冊(cè)模塊,遇到類型不同相比較的時(shí)候,就心驚膽戰(zhàn),每次都要用瀏覽器來驗(yàn)證一下,決定亂七八糟的隨便寫一下,方便日后自己回顧知識(shí)~ 弱類型帶來的那些讓人迷糊的事 弱類型...

    harriszh 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<