你不知道的JavaScript系列---第二章:值es6
任何類型
的值。"稀疏"數組(含有空白或空缺單元
的數組)數組
var a = [] a[0] = 1 a[2] = [3] a[1] // undefined a.length // 3
其中,a[1]
被隱式賦值
爲undefined函數
索引
數組經過數字進行索引,但JavaScript中的數組也是對象,也能夠經過字符串鍵值進行索引(但不計算在數組長度內)工具
var a = [] a[0] = 1 a["foobar"] = 2 a.length // 1 a["foobar"] // 2 a.foobar // 2
當字符串鍵值能夠強制性轉換爲十進制數字
的話,它就會被當作數字索引
處理動畫
var a = [] a["12"] = 1 a.length // 13
固然咱們不建議這麼作(在數組中加入字符串鍵值/屬性
),一般要存放字符串鍵值/屬性,儘可能使用對象
,數組存放數字索引值prototype
類數組
即一系列經過數字索引的值,如:es6以前的arguments
對象(類數組),能夠經過工具函數
將它轉換爲真正的數組指針
function foo () { var arr = Array.prototype.slice.call(arguments) arr.push('amm') console.log(arr) } foo("foo","bar") // ["foo","bar","amm"]
ES6中的Array.from(...)也能夠實現一樣功能code
... var arr = Array.from(arguments) ...
字符串常常被當成字符數組,但它與數組又有極大的不一樣,我感受連類數組也算不上,只是看上去類似而已。
例以下面兩個值對象
var a = "foo" var b = ["f","o","o"]
可是它們兩的確很類似,都有length屬性,indexOf(...)以及concat(...)方法索引
a.length // 3 b.length // 3 a.indexOf("o") // 1 b.indexOf("o") // 1 var c = a.concat("bar") // foobar var d = b.concat(["b","a","r"]) // ["f","o","o","b","a","r"] a === c // false b === d // false a // foo b // ["f","o","o"]
可是它們又有不少不一樣
a[1] = "O" b[1] = "0" a // foo b // ["f","O","o"]
在JavaScript中,字符串是不可變的
,數組可變
,而且a[1]
並非合法語法(老版本IE不支持),正確的應該是a.charAt(1)
字符串不可變是指字符串的成員函數不會改變其原始值,而是建立並返回一個新的字符串,而數組的成員函數都是在其原始值上進行操做。
var c = a.toUpperCase() a === c // fasle a // foo c // FOO b.push("!") b // ["f","o","o", "!"]
JavaScript中,沒有真正意義上的整數,目前只有數字類型(number)
。
二進制浮點數最大的問題:
0.1 + 0.2 === 0.3 // false
從數學的角度來講,此處應該是true,可是二進制浮點數中0.1與0.2並非十分準確,他們相加等於0.30000000000000004
,因此結果爲false。
那麼咱們如何來判斷0.1 + 0.2 和 0.3 是否相等呢?
最多見的方法是設置一個機器偏差
,對於JavaScript中的數字來講,這個值一般是2^-52
.
從ES6
開始,該值定義在Number.EPSILON
中,在指定偏差範圍內,比較兩個數是否相等:
function numbersCloseEnoughEqual(n1, n2) { return Math.abs( n1 - n2 ) < Number.EPSILON } const a = 0.1 + 0.2 const b = 0.3 numbersCloseEnoughEqual(a, b) // true numbersCloseEnoughEqual(0.0000001, 0.0000002)
JavaScript中有幾個特殊的值,須要開發者特別注意和當心使用。
不是數字的數字NaN
:not a number(不是一個數字:無效數值、失敗數值、壞數值)
const a = 2 / 'foo' // NaN typeOf a === number // true
在這裏NaN
是指執行數學運算沒有成功,這是失敗後返回的結果
也許你會認爲,判斷一個數字是不是NaN,只須要將它與NaN做比較就行,如:
2 / "foo" === NaN //false
NaN是一個特殊值,它與自身不相等,惟一一個非自反(x === x 不成立)的值。而NaN != NaN
爲 true
。
那麼咱們可使用工具函數Number.isNaN(...)
來判斷一個值是不是NaN。
零值
JavaScript中有一個常規的0
和一個-0
var a = 0 / -1 // -0 var b = 0 * -3 // -0
加減法不會獲得-0
那麼如何區分他們呢?
function isNegZero(n) { n= Number(n) return (n === 0) && (1 / n === -Infinity) } isNegZero(-0) // true isNegZero(0 / -2) // true isNegZero(0) //false
Infinity
:無窮數
那麼爲何要存在一個-0
?有些應用程序中的數據須要以級數形式來表示(如動畫幀的移動速度),數字的符號位表明特殊信息(如移動的方向)
對於賦值與參數的傳遞能夠經過對值複製
,或者引用複製
來完成,取決於具體的語法。
那麼在JavaScript中,咱們看一個例子:
var a = 2 var b = a // b 是 a 的一個副本 b ++ a // 2 b // 3 var c = [1, 2, 3] var d = c // d 是 [1, 2, 3] 的一個引用 d.push(4) c // [1, 2, 3, 4] d // [1, 2, 3, 4]
簡單值
(基本類型)老是用過值複製
的方式賦值/傳遞複合值
————對象和函數,則是經過引用複製
的方式來複制/傳遞
在JavaScript中,引用指向的是值自己而非變量,因此一個引用沒法改變另外一個引用的指向:
var a = [1,2,3] var b = a a // [1,2,3] b // [1,2,3] // 而後 b = [4,5,6] a // [1,2,3] b // [4,5,6]
b=[4,5,6]
並不影響a的指向[1,2,3]
,除非b指向的是a的指針
,但JavaScript中不存在指針,就不存在這個狀況!
那麼下列狀況,你也許也會明白了:
function foo(x){ x.push(4) x // [1,2,3,4] x = [4,5,6] x.push(7) x // [4,5,6,7] } var a = [1,2,3] foo(a) a // [1,2,3,4]
在函數參數傳遞時,其實是將a的引用
的一個複製品
賦值給x
,經過複製的引用即x更改數組的值,也會影響到a,因此a被改變爲[1,2,3,4]
,可是將x指向到另外一個引用[4,5,6]
,是不會影響到a的指向的,因此a仍是[1,2,3,4]