数组
数组可以容纳任何类型的值,可以是字符串、 数字、对象(object),甚至是其他数组(多维数组就是通过这种方式来实现的)
使用 delete 运算符可以将单元从数组中删除,但是请注意,单元删除后,数 组的 length 属性并不会发生变化。
可以通过下标对数组元素进行索引,但是同时,数组也是对象,所以可以通过点操作符以及[‘’]获取数组元素:
1 | var a = [ ]; |
需要注意的是,当使用[‘1’]数字字符串的性质,会被强制类型转换成十进制数字。
在数组中加入字符串键值 / 属性并不是一个好主意。建议使用对象来存放键值 / 属性值, 用数组来存放数字索引值。
类数组
有时需要将类数组(一组通过数字索引的值)转换为真正的数组,这一般通过数组工具函数(如 indexOf(..)、concat(..)、forEach(..) 等)来实现。
Array.from() 方法返回一个数组复本
1 |
|
字符串
在JavaScript中字符串与字符串数组不是一回事,尽管这两者很相似。
1 | var a = "foo"; |
都有length属性以及indexOf()方法和concat(…) 方法
都可以通过b[1]获取元素, 但是低版本的IE中需要通过a. chartAt(1)方法获取指定下标的字符
一个有趣的事情,我们可以使用数组的方法来处理字符串
1 | a.join; // undefined |
字符串反转的例子,数组有一个方法reverse()
1 | a.reverse; |
一个变通(破解)的办法是先将字符串转换为数组,待处理完后再将结果转换回字符串:
1 | var c = a |
这种方法的确简单粗暴,但对简单的字符串却完全适用。上述方法对于包含复杂字符(Unicode,如星号、多字节字符等)的 字符串并不适用。
数字
JavaScript 只有一种数值类型:number(数字),包括“整数”和带小数的十进制数
指数格式显示,toExponential() 函数
1 | var a = 5E10; |
tofixed(..) 方法可指定小数部分的显示位数:
1 | var a = 42.59; |
toPrecision(..) 方法用来指定有效数位的显示位数::
1 | var a = 42.59; |
较小的数值
0.1 + 0.2 === 0.3; // false
相加的结果是一个比较接近的数字0.30000000000000004
,那么如何判断相加是相等的呢?
设置一个误差范围值:
从 ES6 开始,该值定义在 Number.EPSILON 中,我们可以直接拿来用,也可以为 ES6 之前
的版本写 polyfill:
1 | if (!Number.EPSILON) { |
使用 Number.EPSILON 来比较两个数字是否相等
1 | function numbersCloseEnoughToEqual(n1,n2) { |
数的极限范围
1.798e+308 5e-324(不是负数,但无限接近0)
整数的安全范围
能够被“安全”呈现的最大整数是 2^53 - 1,即 9007199254740991,在 ES6 中被定义为 Number.MAX_SAFE_INTEGER。最小整数是 -9007199254740991,在 ES6 中被定义为 Number. MIN_SAFE_INTEGER。
整数的检测
Number.isInteger(..)方法:
1 | //ES6之前 |
检测一个值是否是安全的整数,number.isSafeInteger(..) 方法:
1 | if (!Number.isSafeInteger) { |
一些特殊的值
null:指的是空值,或者曾经赋值,但现在没有值,初始化时会赋值成null以便于和undefined区分
undefined:指的是没有值,从未赋值
void运算符:通过void运算符可以让表达式返回undefined
NaN:不是数字的数字,如果数学运算的操作数不是数字类型,就无法返回一个有效的数字,这种情况下返回值为NaN,推荐使用ES6中的Number.isNan(..)方法,以避免一些历史遗留的问题
- -0+0: 转换让人迷惑,还是查文档吧
值和引用
引用就像一种特殊的指 针,是来指向变量的指针(别名)。如果参数不声明为引用的话,参数值总是通过值复制 的方式传递,即便对复杂的对象值也是如此。
简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值/传递,包括 null、undefined、字符串、数字、布尔和 ES6 中的 symbol。
复合值(compound value)——对象(包括数组和封装对象,参见第3章)和函数,则总 是通过引用复制的方式来赋值 / 传递。
由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向。
1 | var a = [1,2,3]; |
引用指向的值本身,所以在函数参数传递的时候:
1 | function foo(x) { |
我们无法自行决定使用值复制还是引用复制,一切由值的类型来决定。
值复制
如果通过值复制的方式来传递复合值(如数组),就需要为其创建一个复本,这样传递的 就不再是原始值。例如:
1 | foo( a.slice() ); |
slice(..)不带参数会返回当前数组的一个浅副本,由于传递给函数的是指向该副本的引用,所以在函数中的操作不会影响到a指向的数组。
相反的,如果要将基本数据类型的值传递到函数内,并且修改之,就需要将该值封装套一个复合值(对象或者数组等)中,然后通过引用复制的方式传递
小结
null 类型只有一个值 null,undefined 类型也只有一个值 undefined。所有变量在赋值之 前默认值都是 undefined。void 运算符返回 undefined。
数字类型有几个特殊值,包括 NaN(意指“not a number”,更确切地说是“invalid number”)、+Infinity、-Infinity 和 -0。
简单标量基本类型值(字符串和数字等)通过值复制来赋值 / 传递,而复合值(对象等) 通过引用复制来赋值 / 传递。JavaScript 中的引用和其他语言中的引用 / 指针不同,它们不 能指向别的变量 / 引用,只能指向值。