内置类型
js中有七种内置类型:null
,undefined
,boolean
,number
,string
,object
, symbol
(es6新增)。除了对象外其他统称为基本类型。
我们可以使用typeof
查看值的类型:
console.log(typeof undefined); // undefined
console.log(typeof true); // boolean
console.log(typeof 1); // number
console.log(typeof "str"); // string
console.log(typeof Symbol()); // symbol
console.log(typeof {}); //object
null
有时会被当做对象,即typeof null
为 object
。这实际上是js的一个bug。我们对null
的判断通常是:
const a = null;
if (typeof a === "object" && !a) {
console.log("a is null");
}
因为null
是唯一一个typeof
返回object
,但本身是falsy类型值(也称为“假值”)。
函数作为js的一等公民,也是一个重要的内置类型。它实际上是object
的子类型。属于可调用的对象。
console.log(typeof function () {}); // function
数组也是十分常见的类型,它同样是object
的子类型。
console.log(typeof []); // object
值类型
实际上,js的变量是没有类型的,只有值才有类型。变量可以持有任意类型的值。所以在对变量进行typeof
操作时,得到的结果是该变量持有值的类型。
let a = 1;
console.log(typeof a); // number
a = "str";
console.log(typeof a); // string
typeof typeof SomeValue
总会返回string
。这是因为typeof SomeValue
总会返回一个字符串。
变量在未持有值时(显式赋值),会有一个默认值为undefined
。即typeof
返回undefined
:
let a;
console.log(typeof a); // undefined
如果对一个未声明的变量使用typeof
同样会返回undefined
:
console.log(typeof b); // undefined
注意区分这两种情况,一种是未赋值,另一种是未声明。而如果我们直接使用未声明的变量会报错:
b; // ReferenceError: b is not defined
值
数值
js只有number
类型表示数值类型,包括整数和浮点数:
const a = 1;
const b = 1.2;
小数点前的0
(如0.1
)或者小数部分最后的0
可被省略:
const a = .12; // 等价于 0.12
const b = 1.20000; // 等价于 1.2
对于大数字,可使用科学计数法表示,并且针对特别大或者特别小的数字默认使用指数形式显示:
const a = 3e10; // e大小写皆可
console.log(a); // 30000000000
console.log(a.toExponential()); //以科学计数法形式输出结果 3e+10
console.log(a * a); // 2.7e+31
console.log(1 / a); // 3.3333333333333335e-11
特殊值NaN
如果数学运算符操作不合法,无法返回一个有效的数字时,就会返回NaN
。 NaN
是一个特殊值,表示不是数字的数字(即它的类型还是number
,但它并不算一个数字),没有任何值和它相等,即使是它自身。
const a = 2 / "foo";
console.log(a); // NaN
console.log(typeof NaN); // number
console.log(NaN === NaN); // false
零值
js的0
有两种:+0
,-0
,并且两者是相等的,通常我们的加减运算不会得到-0
结果。
const a = 0 / 1; // 0
const b = 0 / -1; // -0
console.log(-0 === 0); // true
需要-0
的原因:有些应用程序中的数据需要以级数形式来表示(比如动画帧的移动速度),数字符号位用来代表其他信息(比如移动的方向)。此时如果一个值为0
的变量失去了它的符号位,它的方向信息就会丢失。所以保留0
值的符号位可以防止这类情况发生。
特殊值Infinity
js还有一种特殊数值Infinity
,表示无穷:
const a = 1 / 0; // Infinity
const b = -1 / 0; // -Infinity
有穷数除以无穷总返回0
或者-0
(取决于是正数还是负数),无穷除以有穷还是返回无穷,无穷除以无穷返回NaN
。
console.log(1 / Infinity); // 0
console.log(-1 / Infinity); // -0
console.log(Infinity / 10); // Inifinity
console.log(Infinity / -10); // -Inifinity
console.log(Infinity / Infinity); // NaN
由于js遵循IEEE 754规范,所以会出现以下问题:
console.log(0.1 + 0.2 === 0.3); // false
简单来说,0.1
和0.2
的二进制浮点数不是精确的,会无限循环,由于标准位数后多余的会被省略掉,所以出现了精度损失,最后的计算的结果变成0.30000000000000004
。
通常要判断这种情况,可以设置一个误差范围值,js中Number.EPSILON
就表示误差范围值:
console.log(Math.abs(0.3 - (0.1 + 0.2)) < Number.EPSILON); // true
字符串
虽然我们可以对字符串进行修改操作,但字符串本身是不可变的,即在我们修改字符串时,并不改变原始值,而是创建并返回一个新的字符串。
const a = "foo";
const c = a.toUpperCase();
console.log(a === c); // false
数组
js中的数组可以容纳任何类型的值,并且不需要预先设定大小。与字符串不同,数组是可变的。
const a = [1, "2", true];
console.log(a.length); // 3
a.push({ value: 4 });
console.log(a.length); // 4
我们还可以创建”稀疏数组“,即包含空白或者空缺单元的数组:
const a = [];
console.log(a.length); // 0
a[5] = 5;
console.log(a.length); // 6
console.log(a.toString()); // [,,,,,5]
可以看到前5项的数组都为空,如果使用获取前五项的值,会返回undefined
。注意:即使在这种情况下,数组的长度还是变为了6。
数组通常是通过数字进行索引。但正如前面所提到的,数组也是对象的子类型,所以它也可以字符串键值和属性,但是这些属性不会改变数组的length
(通常不建议加入字符串键值和属性)。
const a = [];
a[0] = 1;
console.log(a.length); // 1
a["foo"] = 2;
console.log(a.length); // 1
添加字符串键值时,如果它能够强制转化为非负整数,那么它就会被当做数字索引:
const a = [];
a[0] = 1;
a["1"] = 2;
console.log(a.length); // 2
console.log(a.toString()); // [1,2]