类型和值 -- Javascript基础探究篇(1)

604 阅读4分钟

内置类型

js中有七种内置类型:nullundefinedbooleannumberstringobject, 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

如果数学运算符操作不合法,无法返回一个有效的数字时,就会返回NaNNaN是一个特殊值,表示不是数字的数字(即它的类型还是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.10.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]