你不知道的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]

相关文章
相关标签/搜索