深入理解红宝书(23)

194 阅读5分钟

第五章 基本引用类型

这是我参与8月更文挑战的第23天,活动详情查看: 8月更文挑战

5.3.1 Boolean

Boolean 是对应布尔值的引用类型。要创建一个 Boolean 对象,就使用 Boolean 构造函数并传入 true 或 false,如下例所示:

let booleanObject = new Boolean(true);

Boolean 的实例会重写 valueOf()方法,返回一个原始值 true 或 false。toString()方法被调 用时也会被覆盖,返回字符串"true"或"false"。不过,Boolean 对象在 ECMAScript 中用得很少。 不仅如此,它们还容易引起误会,尤其是在布尔表达式中使用 Boolean 对象时,比如:

let falseObject = new Boolean(false); 
let result = falseObject && true; 
console.log(result); // true 
let falseValue = false; 
result = falseValue && true; 
console.log(result); // false 

在这段代码中,我们创建一个值为 false 的 Boolean 对象。然后,在一个布尔表达式中通过&&操 作将这个对象与一个原始值 true 组合起来。在布尔算术中,false && true 等于 false。可是,这 个表达式是对 falseObject 对象而不是对它表示的值(false)求值。前面刚刚说过,所有对象在布 尔表达式中都会自动转换为 true,因此 falseObject 在这个表达式里实际上表示一个 true 值。那么 true && true 当然是 true。

除此之外,原始值和引用值(Boolean 对象)还有几个区别。首先,typeof 操作符对原始值返回 "boolean",但对引用值返回"object"。同样,Boolean 对象是 Boolean 类型的实例,在使用 instaceof 操作符时返回 true,但对原始值则返回 false,如下所示:

console.log(typeof falseObject); // object 
console.log(typeof falseValue); // boolean 
console.log(falseObject instanceof Boolean); // true 
console.log(falseValue instanceof Boolean); // false 

理解原始布尔值和 Boolean 对象之间的区别非常重要,强烈建议永远不要使用后者。

5.3.2 Number

Number 是对应数值的引用类型。要创建一个 Number 对象,就使用 Number 构造函数并传入一个 数值,如下例所示:

let numberObject = new Number(10); 

与 Boolean 类型一样,Number 类型重写了 valueOf()、toLocaleString()和 toString()方 法。valueOf()方法返回 Number 对象表示的原始数值,另外两个方法返回数值字符串。toString() 方法可选地接收一个表示基数的参数,并返回相应基数形式的数值字符串,如下所示:

let num = 10; 
console.log(num.toString()); // "10" 
console.log(num.toString(2)); // "1010" 
console.log(num.toString(8)); // "12" 
console.log(num.toString(10)); // "10" 
console.log(num.toString(16)); // "a"

除了继承的方法,Number 类型还提供了几个用于将数值格式化为字符串的方法。

toFixed()方法返回包含指定小数点位数的数值字符串,如:

let num = 10; 
console.log(num.toFixed(2)); // "10.00" 

这里的 toFixed()方法接收了参数 2,表示返回的数值字符串要包含两位小数。结果返回值为 "10.00",小数位填充了 0。如果数值本身的小数位超过了参数指定的位数,则四舍五入到最接近的小数位:

let num = 10.005; 
console.log(num.toFixed(2)); // "10.01" 

toFixed()自动舍入的特点可以用于处理货币。不过要注意的是,多个浮点数值的数学计算不一定 得到精确的结果。比如,0.1 + 0.2 = 0.30000000000000004。

注意 toFixed()方法可以表示有 0~20 个小数位的数值。某些浏览器可能支持更大的范 围,但这是通常被支持的范围。

另一个用于格式化数值的方法是 toExponential(),返回以科学记数法(也称为指数记数法)表 示的数值字符串。与 toFixed()一样,toExponential()也接收一个参数,表示结果中小数的位数。 来看下面的例子:

let num = 10; 
console.log(num.toExponential(1)); // "1.0e+1" 

这段代码的输出为"1.0e+1"。一般来说,这么小的数不用表示为科学记数法形式。如果想得到数 值最适当的形式,那么可以使用 toPrecision()。

toPrecision()方法会根据情况返回最合理的输出结果,可能是固定长度,也可能是科学记数法 形式。这个方法接收一个参数,表示结果中数字的总位数(不包含指数)。来看几个例子:

let num = 99; 
console.log(num.toPrecision(1)); // "1e+2" 
console.log(num.toPrecision(2)); // "99" 
console.log(num.toPrecision(3)); // "99.0" 

在这个例子中,首先要用 1 位数字表示数值 99,得到"1e+2",也就是 100。因为 99 不能只用 1 位 数字来精确表示,所以这个方法就将它舍入为 100,这样就可以只用 1 位数字(及其科学记数法形式) 来表示了。用 2 位数字表示 99 得到"99",用 3 位数字则是"99.0"。本质上,toPrecision()方法会 根据数值和精度来决定调用 toFixed()还是 toExponential()。为了以正确的小数位精确表示数值, 这 3 个方法都会向上或向下舍入。

注意 toPrecision()方法可以表示带 1~21 个小数位的数值。某些浏览器可能支持更大 的范围,但这是通常被支持的范围。

与 Boolean 对象类似,Number 对象也为数值提供了重要能力。但是,考虑到两者存在同样的潜在 问题,因此并不建议直接实例化 Number 对象。在处理原始数值和引用数值时,typeof 和 instacnceof 操作符会返回不同的结果,如下所示:

let numberObject = new Number(10); 
let numberValue = 10; 
console.log(typeof numberObject); // "object" 
console.log(typeof numberValue); // "number" 
console.log(numberObject instanceof Number); // true 
console.log(numberValue instanceof Number); // false 

原始数值在调用 typeof 时始终返回"number",而 Number 对象则返回"object"。类似地,Number 对象是 Number 类型的实例,而原始数值不是。

isInteger()方法与安全整数

ES6 新增了 Number.isInteger()方法,用于辨别一个数值是否保存为整数。有时候,小数位的 0 可能会让人误以为数值是一个浮点值:

console.log(Number.isInteger(1)); // true 
console.log(Number.isInteger(1.00)); // true 
console.log(Number.isInteger(1.01)); // false