來源: ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Values, Types, and Operatorsjavascript
譯者:飛龍html
協議:CC BY-NC-SA 4.0java
自豪地採用谷歌翻譯git
部分參考了《JavaScript 編程精解(第 2 版)》github
在機器的表面之下,程序在運轉。 它不費力就能夠擴大和縮小。 在和諧的關係中,電子散開並從新聚合。 監視器上的表格只是水面上的漣漪。 本質隱藏在下面。apache
Master Yuan-Ma,《The Book of Programming》編程
計算機世界裏只有數據。 你能夠讀取數據,修改數據,建立新數據 - 但不能說起不是數據的東西。 全部這些數據都以位的長序列存儲,所以基本類似。函數
位是任何類型的二值的東西,一般描述爲零和一。 在計算機內部,他們有一些形式,例如高電荷或低電荷,強信號或弱信號,或 CD 表面上的亮斑點或暗斑點。 任何一段離散信息均可以簡化爲零和一的序列,從而以位表示。測試
例如,咱們能夠用位來表示數字 13。 它的原理與十進制數字相同,但不是 10 個不一樣的數字,而只有 2 個,每一個數字的權重從右到左增長 2 倍。 如下是組成數字 13 的位,下方顯示數字的權重:this
0 0 0 0 1 1 0 1 128 64 32 16 8 4 2 1
所以,這就是二進制數00001101
,或者8+4+1
,即 13。
想象一下位之海 - 一片它們的海洋。 典型的現代計算機的易失性數據存儲器(工做存儲器)中,有超過 300 億位。非易失性存儲(硬盤或等價物)每每還有幾個數量級。
爲了可以在不丟失的狀況下,處理這些數量的數據,咱們必須將它們分紅表明信息片斷的塊。 在 JavaScript 環境中,這些塊稱爲值。 雖然全部值都是由位構成的,但他們起到不一樣的做用,每一個值都有一個決定其做用的類型。 有些值是數字,有些值是文本片斷,有些值是函數,等等。
要建立一個值,你只須要調用它的名字。 這很方便。 你沒必要爲你的值收集建築材料或爲其付費。 你只須要調用它,而後刷的一下,你就有了它。 固然,它們並非真正憑空創造的。 每一個值都必須存儲在某個地方,若是你想同時使用大量的值,則可能會耗盡內存。 幸運的是,只有同時須要它們時,這纔是一個問題。 只要你再也不使用值,它就會消失,留下它的一部分做爲下一代值的建築材料。
本章將會介紹 JavaScript 程序當中的基本元素,包括簡單的值類型以及值運算符。
數字(Number
)類型的值即數字值。在 JavaScript 中寫成以下形式:
13
在程序中使用這個值的時候,就會將數字 13 以位序列的方式存放在計算機的內存當中。
JavaScript使用固定數量的位(64 位)來存儲單個數字值。 你能夠用 64 位創造不少模式,這意味着能夠表示的不一樣數值是有限的。 對於N
個十進制數字,能夠表示的數值數量是10^N
。 與之相似,給定 64 個二進制數字,你能夠表示2^64
個不一樣的數字,大約 18 億億(18 後面有 18 個零)。太多了。
過去計算機內存很小,人們傾向於使用一組 8 位或 16 位來表示他們的數字。 這麼小的數字很容易意外地溢出,最終獲得的數字不能放在給定的位數中。 今天,即便是裝在口袋裏的電腦也有足夠的內存,因此你能夠自由使用 64 位的塊,只有在處理真正的天文數字時才須要擔憂溢出。
不過,並不是全部 18 億億如下的整數都能放在 JavaScript 數值中。 這些位也存儲負數,因此一位用於表示數字的符號。 一個更大的問題是,也必須表示非整數。 爲此,一些位用於存儲小數點的位置。 能夠存儲的實際最大整數更多地在 9 億億(15 個零)的範圍內 - 這仍然至關多。
使用小數點來表示分數。
9.81
對於很是大或很是小的數字,你也能夠經過輸入e
(表示指數),後面跟着指數來使用科學記數法:
2.998e8
即2.998 * 10^8 = 299,800,000
。
當計算小於前文當中提到的 9000 萬億的整數時,其計算結果會十分精確,不過在計算小數的時候精度卻不高。正如(pi
)沒法使用有限個數的十進制數字表示同樣,在使用 64 位來存儲分數時也一樣會丟失一些精度。雖然說如此,但這類丟失精度只會在一些特殊狀況下才會出現問題。所以咱們須要注意在處理分數時,將其視爲近似值,而非精確值。
與數字密切相關的就是算術。好比,加法或者乘法之類的算術運算會使用兩個數值,併產生一個新的數字。JavaScript 中的算術運算以下所示:
100 + 4 * 11
咱們把+
和*
符號稱爲運算符。第一個符號表示加法,第二個符號表示乘法。將一個運算符放在兩個值之間,該運算符將會使用其旁邊的兩個值產生一個新值。
可是這個例子的意思是「將 4 和 100 相加,並將結果乘 11」,仍是是在加法以前計算乘法? 正如你可能猜到的那樣,乘法首先計算。 可是和數學同樣,你能夠經過將加法包在圓括號中來改變它:
(100 + 4) * 11
–
運算符表示減法,/
運算符則表示除法。
在運算符同時出現,而且沒有括號的狀況下,其運算順序根據運算符優先級肯定。示例中的乘法運算符優先級高於加法。而/
運算符和*
運算符優先級相同,+
運算符和–
運算符優先級也相同。當多個具備相同優先級的運算符相鄰出現時,運算從左向右執行,好比1–2+1
的運算順序是(1–2)+1
。
你無需擔憂這些運算符的優先級規則,不肯定的時候只須要添加括號便可。
還有一個算術運算符,你可能沒法當即認出。 %
符號用於表示取餘操做。 X % Y
是Y
除X
的餘數。 例如,314 % 100
產生14
,144 % 12
產生0
。 餘數的優先級與乘法和除法的優先級相同。 你還常常會看到這個運算符被稱爲模運算符。
在 JavaScript 中有三個特殊的值,它們雖然是數字,但看起來卻跟通常的數字不太同樣。
前兩個是Infinity
和-Infinity
,它們表明正無窮和負無窮。 「無窮減一」仍然是「無窮」,依此類推。 儘管如此,不要過度信任基於無窮大的計算。 它在數學上不合理,而且很快致使咱們的下一個特殊數字:NaN
。
NaN
表明「不是數字」,即便它是數字類型的值。 例如,當你嘗試計算0/0
(零除零),Infinity - Infinity
或任何其餘數字操做,它不會產生有意義的結果時,你將獲得此結果。
下一個基本數據類型是字符串(String
)。 字符串用於表示文本。 它們是用引號括起來的:
`Down on the sea` "Lie on the ocean" 'Float on the ocean'
只要字符串開頭和結尾的引號匹配,就可使用單引號,雙引號或反引號來標記字符串。
幾乎全部的東西均可以放在引號之間,而且 JavaScript 會從中提取字符串值。 但少數字符更難。 你可能不可思議,如何在引號之間加引號。 當使用反引號( `
)引用字符串時,換行符(當你按回車鍵時得到的字符)可能會被包含,而無需轉義。
若要將這些字符存入字符串,須要使用下列規則:當反斜槓(\
)出如今引號之間的文本中時,表示緊跟在其後的字符具備特殊含義,咱們將其稱之爲轉義符。當引號緊跟在反斜槓後時,並不意味着字符串結束,而表示這個引號是字符串的一部分。當字符n
出如今反斜槓後時,JavaScript 將其解釋成換行符。以此類推,\t
表示製表符,咱們來看看下面這個字符串:
"This is the first line\nAnd this is the second"
該字符串實際表示的文本是:
This is the first line And this is the second
固然,在某些狀況下,你但願字符串中的反斜槓只是反斜槓,而不是特殊代碼。 若是兩個反斜槓寫在一塊兒,它們將合併,而且只有一個將留在結果字符串值中。 這就是字符串「A newline character is written like "\n".
」的表示方式:
"A newline character is written like \"\\n\"."
字符串也必須建模爲一系列位,以便可以存在於計算機內部。 JavaScript 執行此操做的方式基於 Unicode 標準。 該標準爲你幾乎須要的每一個字符分配一個數字,包括來自希臘語,阿拉伯語,日語,亞美尼亞語,以及其餘的字符。 若是咱們爲每一個字符分配一個數字,則能夠用一系列數字來描述一個字符串。
這就是 JavaScript 所作的。 可是有一個複雜的問題:JavaScript 的表示爲每一個字符串元素使用 16 位,它能夠描述多達 2 的 16 次方個不一樣的字符。 可是,Unicode 定義的字符多於此 - 大約是此處的兩倍。 因此有些字符,好比許多 emoji,在 JavaScript 字符串中佔據了兩個「字符位置」。 咱們將在第 5 章中回來討論。
咱們不能將除法,乘法或減法運算符用於字符串,可是+
運算符卻能夠。這種狀況下,運算符並不表示加法,而是鏈接操做:將兩個字符串鏈接到一塊兒。如下語句能夠產生字符串"concatenate"
:
"con" + "cat" + "e" + "nate"
字符串值有許多相關的函數(方法),可用於對它們執行其餘操做。 咱們將在第 4 章中回來討論。
用單引號或雙引號編寫的字符串的行爲很是類似 - 惟一的區別是須要在其中轉義哪一種類型的引號。 反引號字符串,一般稱爲模板字面值,能夠實現更多的技巧。 除了可以跨越行以外,它們還能夠嵌入其餘值。
`half of 100 is ${100 / 2}`
當你在模板字面值中的$ {}
中寫入內容時,將計算其結果,轉換爲字符串幷包含在該位置。 這個例子產生"half of 100 is 50"
。
並不是全部的運算符都是用符號來表示,還有一些運算符是用單詞表示的。好比typeof
運算符,會產生一個字符串的值,內容是給定值的具體類型。
console.log(typeof 4.5) // → number console.log(typeof "x") // → string
咱們將在示例代碼中使用console.log
,來表示咱們但願看到求值結果。更多內容請見下一章。
咱們所見過的絕大多數運算符都使用兩個值進行操做,而typeof
僅接受一個值進行操做。使用兩個值的運算符稱爲二元運算符,而使用一個值的則稱爲一元運算符。減號運算符既可用做一元運算符,也可用做二元運算符。
console.log(- (10 - 2)) // → -8
擁有一個值,它能區分兩種可能性,一般是有用的,例如「是」和「否」或「開」和「關」。 爲此,JavaScript 擁有布爾(Boolean
)類型,它有兩個值:true
和false
,它們就寫成這些單詞。
一種產生布爾值的方法以下所示:
console.log(3 > 2) // → true console.log(3 < 2) // → false
>
和<
符號分別表示「大於」和「小於」。這兩個符號是二元運算符,經過該運算符返回的結果是一個布爾值,表示其運算是否爲真。
咱們可使用相同的方法比較字符串。
console.log("Aardvark" < "Zoroaster") // → true
字符串排序的方式大體是字典序,但不真正是你指望從字典中看到的那樣:大寫字母老是比小寫字母「小」,因此"Z"<"A"
,非字母字符(!
,-
等)也包含在排序中。 比較字符串時,JavaScript 從左向右遍歷字符,逐個比較 Unicode 代碼。
其餘相似的運算符則包括>=
(大於等於),<=
(小於等於),==
(等於)和!=
(不等於)。
console.log("Apple" == "Orange") // → false
在 JavaScript 中,只有一個值不等於其自身,那就是NaN
(Not a Number,非數值)。
console.log(NaN == NaN) // → false
NaN
用於表示非法運算的結果,正因如此,不一樣的非法運算結果也不會相等。
還有一些運算符能夠應用於布爾值上。JavaScript 支持三種邏輯運算符:與(and),或(or)和非(not)。這些運算符能夠用於推理布爾值。
&&
運算符表示邏輯與,該運算符是二元運算符,只有當賦給它的兩個值均爲true
時其結果纔是真。
console.log(true && false) // → false console.log(true && true) // → true
||
運算符表示邏輯或。當兩個值中任意一個爲true
時,結果就爲真。
console.log(false || true) // → true console.log(false || false) // → false
感嘆號(!
)表示邏輯非,該運算符是一元運算符,用於反轉給定的值,好比!true
的結果是false
,而!false
結果是true
。
在混合使用布爾運算符和其餘運算符的狀況下,老是很難肯定何時須要使用括號。實際上,只要熟悉了目前爲止咱們介紹的運算符,這個問題就不難解決了。||
優先級最低,其次是&&
,接着是比較運算符(>
,==
等),最後是其餘運算符。基於這些優先級順序,咱們在通常狀況下最好仍是儘可能少用括號,好比說:
1 + 1 == 2 && 10 * 10 > 50
如今咱們來討論最後一個邏輯運算符,它既不屬於一元運算符,也不屬於二元運算符,而是三元運算符(同時操做三個值)。該運算符由一個問號和冒號組成,以下所示。
console.log(true ? 1 : 2); // → 1 console.log(false ? 1 : 2); // → 2
這個被稱爲條件運算符(或者有時候只是三元運算符,由於它是該語言中惟一的這樣的運算符)。 問號左側的值「挑選」另外兩個值中的一個。 當它爲真,它選擇中間的值,當它爲假,則是右邊的值。
有兩個特殊值,寫成null
和undefined
,用於表示不存在有意義的值。 它們自己就是值,但它們沒有任何信息。
在 JavaScript 語言中,有許多操做都會產生無心義的值(咱們會在後面的內容中看到實例),這些操做會獲得undefined
的結果僅僅只是由於每一個操做都必須產生一個值。
undefined
和null
之間的意義差別是 JavaScript 設計的一個意外,大多數時候它並不重要。 在你實際上不得不關注這些值的狀況下,我建議將它們視爲幾乎可互換的。
在引言中,我提到 JavaScript 會盡量接受幾乎全部你給他的程序,甚至是那些作些奇怪事情的程序。 如下表達式很好地證實了這一點:
console.log(8 * null) // → 0 console.log("5" - 1) // → 4 console.log("5" + 1) // → 51 console.log("five" * 2) // → NaN console.log(false == 0) // → true
當運算符應用於類型「錯誤」的值時,JavaScript 會悄悄地將該值轉換爲所需的類型,並使用一組一般不是你想要或指望的規則。 這稱爲類型轉換。 第一個表達式中的null
變爲0
,第二個表達式中的"5"
變爲5
(從字符串到數字)。 然而在第三個表達式中,+
在數字加法以前嘗試字符串鏈接,因此1
被轉換爲"1"
(從數字到字符串)。
當某些不能明顯映射爲數字的東西(如"five"
或undefined
)轉換爲數字時,你會獲得值NaN
。 NaN
進一步的算術運算會產生NaN
,因此若是你發現本身在一個意想不到的地方獲得了它,須要尋找意外的類型轉換。
當相同類型的值之間使用==
符號進行比較時,其運算結果很好預測:除了NaN
這種狀況,只要兩個值相同,則返回true
。但若是類型不一樣,JavaScript 則會使用一套複雜難懂的規則來肯定輸出結果。在絕大多數狀況下,JavaScript 只是將其中一個值轉換成另外一個值的類型。但若是運算符兩側存在null
或undefined
,那麼只有兩側均爲null
或undefined
時結果才爲true
。
console.log(null == undefined); // → true console.log(null == 0); // → false
這種行爲一般頗有用。 當你想測試一個值是否具備真值而不是null
或undefined
時,你能夠用==
(或!=
)運算符將它與null
進行比較。
可是若是你想測試某些東西是否嚴格爲「false」呢? 字符串和數字轉換爲布爾值的規則代表,0
,NaN
和空字符串(""
)計爲false
,而其餘全部值都計爲true
。 所以,像'0 == false'
和"" == false
這樣的表達式也是真的。 當你不但願發生自動類型轉換時,還有兩個額外的運算符:===
和!==
。 第一個測試是否嚴格等於另外一個值,第二個測試它是否不嚴格相等。 因此"" === false
如預期那樣是錯誤的。
我建議使用三字符比較運算符來防止意外類型轉換的發生,避免做繭自縛。但若是比較運算符兩側的值類型是相同的,那麼使用較短的運算符也沒有問題。
邏輯運算符&&
和||
以一種特殊的方式處理不一樣類型的值。 他們會將其左側的值轉換爲布爾型,來決定要作什麼,但根據運算符和轉換結果,它們將返回原始的左側值或右側值。
例如,當左側值能夠轉換爲true
時,||
運算符會返回它,不然返回右側值。 當值爲布爾值時,這具備預期的效果,而且對其餘類型的值作相似的操做。
console.log(null || "user") // → user console.log("Agnes" || "user") // → Agnes
咱們能夠此功能用做回落到默認值的方式。 若是你的一個值多是空的,你能夠把||
和備選值放在它以後。 若是初始值能夠轉換爲false
,那麼你將獲得備選值。
&&
運算符工做方式與其類似但不相同。當左側的值能夠被轉換成false
時,&&
運算符會返回左側值,不然返回右側值。
這兩個運算符的另外一個重要特性是,只在必要時求解其右側的部分。 在true || X
的狀況下,無論X
是什麼 - 即便它是一個執行某些惡意操做的程序片斷,結果都是true
,而且X
永遠不會求值。 false && X
也是同樣,它是false
的,而且忽略X
。 這稱爲短路求值。
條件運算符以相似的方式工做。 在第二個和第三個值中,只有被選中的值纔會求值。
在本章中,咱們介紹了 JavaScript 的四種類型的值:數字,字符串,布爾值和未定義值。
經過輸入值的名稱(true
,null
)或值(13
,"abc"
)就能夠建立它們。你還能夠經過運算符來對值進行合併和轉換操做。本章已經介紹了算術二元運算符(+
,–
,*
,/
和%
),字符串鏈接符(+
),比較運算符(==
,!=
,===
,!==
,<
,>
,<=
和>=
),邏輯運算符(&&
和||
)和一些一元運算符(–
表示負數,!
表示邏輯非,typeof
用於查詢值的類型)。
這爲你提供了足夠的信息,將 JavaScript 用做便攜式計算器,但並很少。 下一章將開始將這些表達式綁定到基本程序中。