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

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript中,{}+{} 等于多少?

Jrain / 2699人閱讀

摘要:如果返回值是一個(gè)原始值,則返回這個(gè)原始值。如果或者中的任意一個(gè)為字符串,則將另外一個(gè)也轉(zhuǎn)換成字符串,然后返回兩個(gè)字符串連接操作后的結(jié)果。因此,的結(jié)果實(shí)際上是兩個(gè)空字符串的連接。

原文:What is {} + {} in JavaScript?

譯者:justjavac


最近,Gary Bernhardt 在一個(gè)簡(jiǎn)短的演講視頻“Wat”中指出了一個(gè)有趣的 JavaScript 怪癖: 在把對(duì)象和數(shù)組混合相加時(shí),會(huì)得到一些意想不到的結(jié)果。 本篇文章會(huì)依次講解這些計(jì)算結(jié)果是如何得出的。

在 JavaScript 中,加法的規(guī)則其實(shí)很簡(jiǎn)單,只有兩種情況:

把數(shù)字和數(shù)字相加

把字符串和字符串相加

所有其他類(lèi)型的值都會(huì)被自動(dòng)轉(zhuǎn)換成這兩種類(lèi)型的值。 為了能夠弄明白這種隱式轉(zhuǎn)換是如何進(jìn)行的,我們首先需要搞懂一些基礎(chǔ)知識(shí)。

注意:在下面的文章中提到某一章節(jié)的時(shí)候(比如§9.1),指的都是 ECMA-262 語(yǔ)言規(guī)范(ECMAScript 5.1)中的章節(jié)。

讓我們快速的復(fù)習(xí)一下。 在 JavaScript 中,一共有兩種類(lèi)型的值:

原始值(primitives)

undefined

null

boolean

number

string

對(duì)象值(objects)。

除了原始值外,其他的所有值都是對(duì)象類(lèi)型的值,包括數(shù)組(array)和函數(shù)(function)。

類(lèi)型轉(zhuǎn)換

加法運(yùn)算符會(huì)觸發(fā)三種類(lèi)型轉(zhuǎn)換:

轉(zhuǎn)換為原始值

轉(zhuǎn)換為數(shù)字

轉(zhuǎn)換為字符串

通過(guò) ToPrimitive() 將值轉(zhuǎn)換為原始值

JavaScript 引擎內(nèi)部的抽象操作 ToPrimitive() 有著這樣的簽名:

ToPrimitive(input,PreferredType?)

可選參數(shù) PreferredType 可以是 Number 或者 String。 它只代表了一個(gè)轉(zhuǎn)換的偏好,轉(zhuǎn)換結(jié)果不一定必須是這個(gè)參數(shù)所指的類(lèi)型(汗),但轉(zhuǎn)換結(jié)果一定是一個(gè)原始值。 如果 PreferredType 被標(biāo)志為 Number,則會(huì)進(jìn)行下面的操作來(lái)轉(zhuǎn)換 input (§9.1):

如果 input 是個(gè)原始值,則直接返回它。

否則,如果 input 是一個(gè)對(duì)象。則調(diào)用 obj.valueOf() 方法。 如果返回值是一個(gè)原始值,則返回這個(gè)原始值。

否則,調(diào)用 obj.toString() 方法。 如果返回值是一個(gè)原始值,則返回這個(gè)原始值。

否則,拋出 TypeError 異常。

如果 PreferredType 被標(biāo)志為 String,則轉(zhuǎn)換操作的第二步和第三步的順序會(huì)調(diào)換。 如果沒(méi)有 PreferredType 這個(gè)參數(shù),則 PreferredType 的值會(huì)按照這樣的規(guī)則來(lái)自動(dòng)設(shè)置:

Date 類(lèi)型的對(duì)象會(huì)被設(shè)置為 String

其它類(lèi)型的值會(huì)被設(shè)置為 Number

通過(guò) ToNumber() 將值轉(zhuǎn)換為數(shù)字

下面的表格解釋了 ToNumber() 是如何將原始值轉(zhuǎn)換成數(shù)字的 (§9.3)。

參數(shù) 結(jié)果
undefined NaN
null +0
boolean true被轉(zhuǎn)換為1,false轉(zhuǎn)換為+0
number 無(wú)需轉(zhuǎn)換
string 由字符串解析為數(shù)字。例如,"324"被轉(zhuǎn)換為324

如果輸入的值是一個(gè)對(duì)象,則會(huì)首先會(huì)調(diào)用 ToPrimitive(obj, Number) 將該對(duì)象轉(zhuǎn)換為原始值, 然后在調(diào)用 ToNumber() 將這個(gè)原始值轉(zhuǎn)換為數(shù)字。

通過(guò)ToString()將值轉(zhuǎn)換為字符串

下面的表格解釋了 ToString() 是如何將原始值轉(zhuǎn)換成字符串的(§9.8)。

參數(shù) 結(jié)果
undefined "undefined"
null "null"
boolean "true" 或者 "false"
number 數(shù)字作為字符串。比如,"1.765"
string 無(wú)需轉(zhuǎn)換

如果輸入的值是一個(gè)對(duì)象,則會(huì)首先會(huì)調(diào)用 ToPrimitive(obj, String) 將該對(duì)象轉(zhuǎn)換為原始值, 然后再調(diào)用 ToString() 將這個(gè)原始值轉(zhuǎn)換為字符串。

實(shí)踐一下

下面的對(duì)象可以讓你看到引擎內(nèi)部的轉(zhuǎn)換過(guò)程。

var obj = {
    valueOf: function () {
        console.log("valueOf");
        return {}; // not a primitive
    },
    toString: function () {
        console.log("toString");
        return {}; // not a primitive
    }
}

Number 作為一個(gè)函數(shù)被調(diào)用(而不是作為構(gòu)造函數(shù)調(diào)用)時(shí),會(huì)在引擎內(nèi)部調(diào)用 ToNumber() 操作:

> Number(obj)
valueOf
toString
TypeError: Cannot convert object to primitive value
加法

有下面這樣的一個(gè)加法操作。

value1 + value2

在計(jì)算這個(gè)表達(dá)式時(shí),內(nèi)部的操作步驟是這樣的 (§11.6.1):

將兩個(gè)操作數(shù)轉(zhuǎn)換為原始值 (以下是數(shù)學(xué)表示法的偽代碼,不是可以運(yùn)行的 JavaScript 代碼):

prim1 := ToPrimitive(value1)
prim2 := ToPrimitive(value2)

PreferredType 被省略,因此 Date 類(lèi)型的值采用 String,其他類(lèi)型的值采用 Number

如果 prim1 或者 prim2 中的任意一個(gè)為字符串,則將另外一個(gè)也轉(zhuǎn)換成字符串,然后返回兩個(gè)字符串連接操作后的結(jié)果。

否則,將 prim1 和 prim2 都轉(zhuǎn)換為數(shù)字類(lèi)型,返回他們的和。

預(yù)料到的結(jié)果

當(dāng)你將兩個(gè)數(shù)組相加時(shí),結(jié)果正是我們期望的:

> [] + []
""

[] 被轉(zhuǎn)換成一個(gè)原始值:首先嘗試 valueOf() 方法,該方法返回?cái)?shù)組本身(this):

> var arr = [];
> arr.valueOf() === arr
true

此時(shí)結(jié)果不是原始值,所以再調(diào)用 toString() 方法,返回一個(gè)空字符串(string 是原始值)。 因此,[] + [] 的結(jié)果實(shí)際上是兩個(gè)空字符串的連接。

將一個(gè)數(shù)組和一個(gè)對(duì)象相加,結(jié)果依然符合我們的期望:

> [] + {}
"[object Object]"

解析:將空對(duì)象轉(zhuǎn)換成字符串時(shí),產(chǎn)生如下結(jié)果。

> String({})
"[object Object]"

所以最終的結(jié)果其實(shí)是把 """[object Object]" 兩個(gè)字符串連接起來(lái)。

更多的對(duì)象轉(zhuǎn)換為原始值的例子:

> 5 + new Number(7)
12
> 6 + { valueOf: function () { return 2 } }
8
> "abc" + { toString: function () { return "def" } }
"abcdef"
意想不到的結(jié)果

如果 + 加法運(yùn)算的第一個(gè)操作數(shù)是個(gè)空對(duì)象字面量,則會(huì)出現(xiàn)詭異的結(jié)果(Firefox console 中的運(yùn)行結(jié)果):

> {} + {}
NaN

天哪!神馬情況?(譯注:原文沒(méi)有,是我第一次讀到這兒的時(shí)候感到太吃驚了,翻譯的時(shí)候加入的。) 這個(gè)問(wèn)題的原因是,JavaScript 把第一個(gè) {} 解釋成了一個(gè)空的代碼塊(code block)并忽略了它。 NaN 其實(shí)是表達(dá)式 +{} 計(jì)算的結(jié)果 (+ 加號(hào)以及第二個(gè) {})。 你在這里看到的 + 加號(hào)并不是二元運(yùn)算符「加法」,而是一個(gè)一元運(yùn)算符,作用是將它后面的操作數(shù)轉(zhuǎn)換成數(shù)字,和 Number() 函數(shù)完全一樣。例如:

> +"3.65"
3.65

以下的表達(dá)式是它的等價(jià)形式:

+{}
Number({})
Number({}.toString())  // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN

為什么第一個(gè) {} 會(huì)被解析成代碼塊(code block)呢? 因?yàn)檎麄€(gè)輸入被解析成了一個(gè)語(yǔ)句:如果左大括號(hào)出現(xiàn)在一條語(yǔ)句的開(kāi)頭,則這個(gè)左大括號(hào)會(huì)被解析成一個(gè)代碼塊的開(kāi)始。 所以,你也可以通過(guò)強(qiáng)制把輸入解析成一個(gè)表達(dá)式來(lái)修復(fù)這樣的計(jì)算結(jié)果: (譯注:我們期待它是個(gè)表達(dá)式,結(jié)果卻被解析成了語(yǔ)句,表達(dá)式和語(yǔ)句的區(qū)別可以查看我以前的『代碼之謎』系列的 語(yǔ)句與表達(dá)式。)

> ({} + {})
"[object Object][object Object]"

一個(gè)函數(shù)或方法的參數(shù)也會(huì)被解析成一個(gè)表達(dá)式:

> console.log({} + {})
[object Object][object Object]

經(jīng)過(guò)前面的講解,對(duì)于下面這樣的計(jì)算結(jié)果,你也應(yīng)該不會(huì)感到吃驚了:

> {} + []
0

在解釋一次,上面的輸入被解析成了一個(gè)代碼塊后跟一個(gè)表達(dá)式 +[]。 轉(zhuǎn)換的步驟是這樣的:

+[]
Number([])
Number([].toString())  // [].valueOf() isn’t primitive
Number("")
0

有趣的是,Node.js 的 REPL 在解析類(lèi)似的輸入時(shí),與 Firefox 和 Chrome(和Node.js 一樣使用 V8 引擎) 的解析結(jié)果不同。 下面的輸入會(huì)被解析成一個(gè)表達(dá)式,結(jié)果更符合我們的預(yù)料:

> {} + {}
"[object Object][object Object]"
> {} + []
"[object Object]"
3. 這就是所有嗎?

在大多數(shù)情況下,想要弄明白 JavaScript 中的 + 號(hào)是如何工作的并不難:你只能將數(shù)字和數(shù)字相加或者字符串和字符串相加。 對(duì)象值會(huì)被轉(zhuǎn)換成原始值后再進(jìn)行計(jì)算。如果將多個(gè)數(shù)組相加,可能會(huì)出現(xiàn)你意料之外的結(jié)果,相關(guān)文章請(qǐng)參考在 javascript 中,為什么 [1,2] + [3,4] 不等于 [1,2,3,4]? 和 為什么 ++[[]][+[]]+[+[]] = 10?。

如果你想連接多個(gè)數(shù)組,需要使用數(shù)組的 concat 方法:

> [1, 2].concat([3, 4])
[1, 2, 3, 4]

JavaScript 中沒(méi)有內(nèi)置的方法來(lái)“連接" (合并)多個(gè)對(duì)象。 你可以使用一個(gè) JavaScript 庫(kù),比如 Underscore:

> var o1 = {eeny:1, meeny:2};
> var o2 = {miny:3, moe: 4};
> _.extend(o1, o2)
{eeny: 1, meeny: 2, miny: 3, moe: 4}

注意:和 Array.prototype.concat() 方法不同,extend() 方法會(huì)修改它的第一個(gè)參數(shù),而不是返回合并后的對(duì)象:

> o1
{eeny: 1, meeny: 2, miny: 3, moe: 4}
> o2
{miny: 3, moe: 4}

如果你想了解更多有趣的關(guān)于運(yùn)算符的知識(shí),你可以閱讀一下 “Fake operator overloading in JavaScript”(中文正在翻譯中)。

參考

JavaScript 并非所有的東西都是對(duì)象

JavaScript:將所有值都轉(zhuǎn)換成對(duì)象

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

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

相關(guān)文章

  • 前端資源系列(5)-JavaScript奇味探索

    摘要:中有很多奇妙的東西,歸咎歸功于設(shè)計(jì)時(shí)候的迅速。缺陷有,但是的強(qiáng)大確實(shí)體現(xiàn)的淋漓盡致。它是如此的靈活,當(dāng)然隨之而來(lái)的便是開(kāi)發(fā)的代價(jià),它不像強(qiáng)類(lèi)型語(yǔ)言那樣規(guī)規(guī)矩矩。難得周末晚上清閑,回味這些看起來(lái)有點(diǎn)怪怪卻又在發(fā)生著的問(wèn)題。 JavaScript中有很多奇妙的東西,歸咎or歸功于設(shè)計(jì)時(shí)候的迅速。缺陷有,但是JavaScript的強(qiáng)大確實(shí)體現(xiàn)的淋漓盡致。 它是如此的靈活,當(dāng)然隨之而來(lái)的便是開(kāi)...

    kyanag 評(píng)論0 收藏0
  • 數(shù)據(jù)類(lèi)型 數(shù)值

    摘要:報(bào)錯(cuò)報(bào)錯(cuò)報(bào)錯(cuò)有前導(dǎo)的數(shù)值會(huì)被視為八進(jìn)制,但是如果前導(dǎo)后面有數(shù)字和,則該數(shù)值被視為十進(jìn)制。對(duì)于那些會(huì)自動(dòng)轉(zhuǎn)為科學(xué)計(jì)數(shù)法的數(shù)字,會(huì)將科學(xué)計(jì)數(shù)法的表示方法視為字符串,因此導(dǎo)致一些奇怪的結(jié)果。 1.概述1.1整數(shù)和浮點(diǎn)數(shù)1.2數(shù)值精度1.3數(shù)值范圍2.數(shù)值的表示法3.數(shù)值的進(jìn)制4.特殊數(shù)值4.1正零和負(fù)零4.2NaN4.3Infinity5.與數(shù)值相關(guān)的全局方法5.1parseInt()5.2...

    lavor 評(píng)論0 收藏0
  • JavaScript 數(shù)據(jù)結(jié)構(gòu)與算法之美 - 歸并排序、快速排序、希爾排序、堆排序

    摘要:之所以把歸并排序快速排序希爾排序堆排序放在一起比較,是因?yàn)樗鼈兊钠骄鶗r(shí)間復(fù)雜度都為。歸并排序是一種穩(wěn)定的排序方法。因此,快速排序并不穩(wěn)定。希爾排序思想先將整個(gè)待排序的記錄序列分割成為若干子序列。 showImg(https://segmentfault.com/img/bVbvpYZ?w=900&h=250); 1. 前言 算法為王。 想學(xué)好前端,先練好內(nèi)功,只有內(nèi)功深厚者,前端之路才...

    haitiancoder 評(píng)論0 收藏0
  • 2019-我的前端面試題

    摘要:先說(shuō)下我面試情況,我一共面試了家公司。篇在我面試的眾多公司里,只有同城的面問(wèn)到相關(guān)問(wèn)題,其他公司壓根沒(méi)問(wèn)。我自己回答的是自己開(kāi)發(fā)組件面臨的問(wèn)題。完全不用擔(dān)心對(duì)方到時(shí)候打電話(huà)核對(duì)的問(wèn)題。 2019的5月9號(hào),離發(fā)工資還有1天的時(shí)候,我的領(lǐng)導(dǎo)親切把我叫到辦公室跟我說(shuō):阿郭,我們公司要倒閉了,錢(qián)是沒(méi)有的啦,為了不耽誤你,你趕緊出去找工作吧。聽(tīng)到這話(huà),我虎軀一震,這已經(jīng)是第2個(gè)月沒(méi)工資了。 公...

    iKcamp 評(píng)論0 收藏0
  • 100塊錢(qián)換零錢(qián),最多有多少種方式的 JavaScript 版本實(shí)現(xiàn)

    摘要:原文鏈接歡迎現(xiàn)在有塊錢(qián)人民幣,將塊錢(qián)換成零錢(qián)最小幣值元,一共有多少方式總的不同方式的數(shù)目等于將現(xiàn)金數(shù)換成除第一種幣值之外的所有其他硬幣的不同方式數(shù)據(jù),加上將現(xiàn)金數(shù)第一種幣值換成所有種類(lèi)的幣值的不同方式,根據(jù)上面的說(shuō)法來(lái)實(shí)現(xiàn)吧實(shí)現(xiàn)中的是中的 原文鏈接: 歡迎 Star 現(xiàn)在有100塊錢(qián)人民幣,將 100 塊錢(qián)換成零錢(qián)(最小幣值 1 元),一共有多少方式? 總的不同方式的數(shù)目等于: 將現(xiàn)...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<