1. 数组
(1)数组可以容纳任何类型的值,可以是字符串、数字、对象,甚至是其他数组。
(2)对数组声明后即可向其中加入值,不需要预先设定大小。
(3)使用delete运算符可以将单元从数组中删除,但是请注意,单元删除后,数组的length属性并不会发生变化,被删除的单元变成了undefined。
(4)创建稀疏数组时,空白单元的值是undefined,但是与显示将其赋值为undefined有所区别。
(5)数组可以通过数字进行索引,但由于数组也是对象,所以它也可以包含字符串键值和属性(但不算在数组长度内)。
var a = [];
a[0] = 1;
a["floor"] = 2;
a.length; // 1
a["floor"] // 2
a.floor // 2
(6)如果字符串键值能够被强制类型转换成十进制数字的话,它就会被当作数字所以来处理。
var a = [];
a["13"] = 42;
a.length; // 14
(7)在数组中加入字符串键值/属性不是一个好主意,建议使用对象来存放键值/属性,使用数组来存放数组索引值。
2. 字符串
(1)字符串和字符数组不是一回事,字符串不可变,字符数组可变。
(2)字符串不可改变,因此想要将字符串反转,可以先将字符串转换成数组,待处理完毕后再将结果转换成字符串。
var a = "foo";
var c = a.split("").reverse().join("");
c; // "oof"
(3)上述方法不适用于包含复杂字符(Unicode,如星号、多字节字符等)
3. 数字
(1)js使用双精度格式(64位二进制)保存数字(number)。
(2)数字常量也可以直接使用.(点号)运算符调用函数,但是.(点号)会被优先识别为数字的一部分。
42.toFixed(3); // 无效语法,.被视为42.的一部分
(42).toFixed(3); // 有效,"42.000"
0.42.toFixed(3); // 有效,"0.420"
42..toFixed(3); // 有效,"42.000"
42 .toFixed(3); // 有效,"42.000",注意42与.之间有个空格
4. 特殊数值
(1)undefined类型只有一个值,即undefined,null类型也只有一个值,即null。
(2)undefined指没有值(missing value),null指空值(empty value)。
(3)使用void可以得到undefined,比如void 0; // undefined
(4)NaN意指“不是一个数字(Not a Number)”,NAN是js中唯一一个不等于自身的值
typeof NaN; // "number",说明NaN是数字类型
var a = 2 / "foo"; // NaN
a == NaN; // false
a === NaN; // false
NaN !== NaN; // true
(5)不要用isNaN()函数判断一个值是否是NaN,该函数有严重缺陷,要使用ES6的Number.isNaN()函数
// ES6之前可以用以下方法判断是否是NaN
if (!Number.isNaN) {
Number.isNaN = function(n) {
return (typeof n === "number" && window.isNaN(n));
};
}
// 还可以利用NaN是唯一一个不等于自身值的特性
if (!Number.isNaN) {
Number.isNaN = function(n) {
return (n !== n);
};
}
(6)ES6中新加入了一个工具方法Object.is()来判断两个值是否绝对相等,可以用来处理上述特殊情况,但尽量少用,因为效率较低。
5. 值和引用
(1)简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值/传递,包括null、undefined、string、number、boolean和symbol
(2)复合值(compound value)--对象(包括数组和封装对象)和函数,则总是通过引用复制的方式来赋值/传递。
(3)以下函数会让人产生困惑:
function foo(x)
{
x.push(4);
x; // [1, 2, 3, 4]
// x重新赋值,相当于重新开辟了一块内存,x不再使用原来的内存,因此这个赋值不会影响到入参的那个x
x = [4, 5, 6];
x.push(7);
x; // [4, 5, 6, 7]
}
var a = [1, 2, 3];
foo(a);
a; // 是[1, 2, 3, 4],不是[4, 5, 6, 7]
function foo(x)
{
x.push(4);
x; // [1, 2, 3, 4]
// x清空,即将x原来的内存清空,再在原来的内存里面重新写入值,因此会改变到入参的那个x
x.length = 0;
x.push(4, 5, 6, 7);
x; // [4, 5, 6, 7]
}
var a = [1, 2, 3];
foo(a);
a; // 是[4, 5, 6, 7],不是[1, 2, 3, 4]