你不知道的JavaScript :值

你不知道的JavaScript系列---第二章:值es6

2.1 數組

  • JavaScript裏面的數組能夠容納任何類型的值。
  • "稀疏"數組(含有空白或空缺單元的數組)數組

    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)
    ...

2.2 字符串

字符串常常被當成字符數組,但它與數組又有極大的不一樣,我感受連類數組也算不上,只是看上去類似而已。
例以下面兩個值對象

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", "!"]

2.3 數字

JavaScript中,沒有真正意義上的整數,目前只有數字類型(number)

2.3.1 較小的數值

二進制浮點數最大的問題:

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)

2.3.2 特殊數值

JavaScript中有幾個特殊的值,須要開發者特別注意和當心使用。

  1. 不是數字的數字
    NaN:not a number(不是一個數字:無效數值、失敗數值、壞數值)

    const a = 2 / 'foo' // NaN
    typeOf a === number // true

    在這裏NaN是指執行數學運算沒有成功,這是失敗後返回的結果
    也許你會認爲,判斷一個數字是不是NaN,只須要將它與NaN做比較就行,如:

    2 / "foo" === NaN //false

    NaN是一個特殊值,它與自身不相等,惟一一個非自反(x === x 不成立)的值。而
    NaN != NaNtrue
    那麼咱們可使用工具函數Number.isNaN(...)來判斷一個值是不是NaN。

  2. 零值
    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?有些應用程序中的數據須要以級數形式來表示(如動畫幀的移動速度),數字的符號位表明特殊信息(如移動的方向)

2.4 值和引用

對於賦值與參數的傳遞能夠經過對值複製,或者引用複製來完成,取決於具體的語法。
那麼在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]

相關文章
相關標籤/搜索