数字转换
将数据类型转换为数字称为数字转换,可以使用Number()
、parseInt()
、parseFloat()
等方法将数据类型显式转换为数字。当一个值不能被强制转换为一个数字时,就会返回 NaN
。
1. 字符串 => 数字:
当把字符串转换为数字时,JavaScript 引擎首先会修剪前导和后置空格、\n
、\t
字符,如果修剪后的字符串不代表有效数字,则返回 NaN
。 如果字符串为空,则返回 0。
Number('123'); // 123
Number("-12.34") // -12.34
Number("12s"); // NaN
Number("\n") // 0
parseInt(' 203px'); // 203
parseInt('10.000') // 10
parseInt('10.20') // 10
parseFloat('203.212px'); // 203.212
parseFloat('10.20') // 10.2
parseFloat('10.81') // 10.81
可以看到,parseInt
函数会从字符串中读取一个数字并删除它后面所有字符,但是如果数字前面有字符(空格除外),那么它将输出 NaN
。
2. 布尔值 => 数字:
当使用 Number()
将布尔值转化为数字时,true
会转化为 1,false
会转化为 0。
Number(true); // 1
Number(false); // 0
3. null => 数字:
当使用 Number()
将 null
转化为数字时,会返回 0:
Number(null); // 0
null + 5; // 5
4. undefined / 数组 / 对象 / NaN => 数字:
当使用 Number()
将 undefined
、数组、对象、NaN
转化为数字时,会返回 NaN
:
Number(undefined); // NaN
Number([1, 2, 3]) // NaN
Number({}) // NaN
Number(NaN) // NaN
5. 数组元素
可以使用map
遍历数组元素,并使用需要的类型来进行类型转换:
["1", "9", "-9", "0.003", "yes"].map(Number);
// 输出结果:[1, 9, -9, 0.003, NaN]
6. 特殊规则
在表达式中,当我们将 ==
运算符应用于 null
或 undefined
时,不会发生数字转换。 此外,null
只等于 null
或 undefined
,不能等于其他任何值:
null == null; // true
null == 0; // false
null == undefined; // true
undefined == undefined // true
根据运算符优先级,+
运算符具有从左到右的关联性,因此如果有一个表达式 2 + 3 + '4' + 'number'
,则操作按以下方式完成:
2 + 3 + '4' + 'number'
==> 5 + '4' + 'number'
// 数字 5 被隐式转换为字符串,然后连接起来
==> '54' + 'number'
==> '54number'
NaN
不等于任何其他类型,甚至它本身:
NaN == NaN // false
7. 总结
上面的例子中,可以清楚地看到一些意想不到的结果:将 null
转换为数字时返回了 0,而将 undefined
转换为数字返回了 NaN
。两个操作都应该返回 NaN
,因为这两种值类型显然都不是有效的数字,将空字符串转换为数字时也返回了 0。
下面是 ECMAScript 规范中将数据类型转换为字符串的规则,清楚的解释了上面的异常现象:
另外,在 ECMAScript 规范中,还提到一点:
意思就是:为空或仅包含空格的 StringNumericLiteral 将转换为 +0。这也就解释了为什么将空字符串转换为数字时也返回了 0。
ECMAScript 规范: https://262.ecma-international.org/5.1/#sec-9.3
Symbol 类型转换
1. 创建并使用 Symbol 类型
我们可以使用 Symbol 函数来创建 Symbol 类型的值:
const mySymbol = Symbol();
console.log(typeof mySymbol); // 输出: "symbol"
上述代码创建了一个名为 mySymbol 的 Symbol 类型的值,并将其打印出来。注意到 typeof 操作符返回的结果是 "symbol",这表示该值是 Symbol 类型。
Symbol 类型的值可用于作为对象的属性名,以确保属性的唯一性。例如:
const mySymbol = Symbol("mySymbol");
const obj = {
[mySymbol]: "Hello Symbol",
};
console.log(obj[mySymbol]); // 输出: "Hello Symbol"
在上述代码中,我们创建了一个带有描述符的 Symbol 值,并将其用作对象 obj 的属性名。通过使用方括号表示法,我们可以访问该属性并输出其值。
2. Symbol 转换为字符串、布尔值和数字
在 JavaScript 中,我们可以将 Symbol 类型的值转换为字符串、布尔值和数字类型。要将 Symbol 转换为字符串,可以使用 Symbol 值的 .toString() 方法或者调用 String() 函数。例如:
const mySymbol = Symbol("mySymbol");
console.log(mySymbol.toString()); // 输出: "Symbol(mySymbol)"
console.log(String(mySymbol)); // 输出: "Symbol(mySymbol)"
在上述代码中,我们分别使用 .toString() 方法和 String() 函数将 Symbol 值转换为字符串。
然而,Symbol 类型的值不能直接与布尔值或数字进行转换,因为它们在不同的类型之间没有直接的关联。
3. 将其他类型转换为 Symbol
除了 Symbol 类型转换为其他类型,我们还可以将其他类型转换为 Symbol。为了将其他类型的值转换为 Symbol 类型,我们可以使用 Symbol() 函数并传递一个可选的描述符字符串作为参数:
const strSymbol = Symbol("string");
const boolSymbol = Symbol(Boolean(true));
const numSymbol = Symbol(Number(42));
在上述代码中,我们创建了三个不同的 Symbol 类型的值,并将分别将字符串、布尔值和数字类型的值转换为 Symbol 类型。
Symbol
只能进行显式转换,不能进行隐式转换。也就是说,Symbol
不能被强制转换为字符串或数字,这样它们就不会被意外地用作本来应该表现为 Symbol
的属性。
const mySymbol = Symbol.for("mySymbol");
const str = String(mySymbol);
console.log(str); // 'Symbol(mySymbol)'
当使用 console.log()
来打印 symbol
时,它之所以有效,是因为 console.log()
在 symbol
上调用了 String()
方法以创建可用的结果。
如果尝试直接使用字符串连接 symbol
,它将抛出TypeError
:
const mySymbol = Symbol.for("mySymbol");
const sum = mySymbol + "";
console.log(sum); // Uncaught TypeError: Cannot convert a Symbol value to a string
将 mySymbol
连接到字符串需要首先将 mySymbol
转换为字符串,并且在检测到强制转换时会抛出错误,从而阻止以这种方式使用它。
同样,我们不能将 symbol
强制转换为数字,所有数学运算符在与符号一起使用时都会引发错误:
const mySymbol = Symbol.for("mySymbol");
const factor = mySymbol / 2;
console.log(factor); // Uncaught TypeError: Cannot convert a Symbol value to a number