跳到主要内容

JS 中的隐式类型转换 3

在 JavaScript 中,当我们对不同类型的值进行运算时,会涉及到隐式类型转换。本文将深入探讨 JavaScript 中的隐式类型转换规则。

String 类型转换

当我们将一个值转换为 String 类型时,有以下几种情况:

  1. 对于包装类 String,会调用 toString 方法将值转换为字符串。

  2. 对于对象,通过 String 方法进行包装时,会先查找对象上的 toString 方法。

  3. 对于原始值数据类型,调用 toString 方法时,实际上是调用该类型原型上的 toString 方法。

  4. 对于引用值,调用 toString 方法时,具体行为取决于对象自身的实现。

下面是一个示例

var obj = {
toString() {
return 1;
},
valueOf() {
return 2;
},
};
console.log(String(obj)); // "1"
// 等价于 "" + obj

toString 和 valueOf 方法

在隐式类型转换过程中,toString 和 valueOf 方法扮演着重要角色:

  1. toString 方法将一个值转换为字符串类型。

  2. valueOf 方法返回一个值的原始值表示。

当将一个对象转换为字符串时,会先调用 toString 方法。如果 toString 方法返回的不是原始值,则继续调用 valueOf 方法。

var obj = {
toString() {
return {};
},
valueOf() {
return '123';
},
};
console.log(String(obj)); // "123"

Number 类型转换

当我们将一个值转换为 Number 类型时,会先调用 valueOf 方法获取原始值。如果 valueOf 方法返回的不是原始值,则继续调用 toString 方法。

var obj = {
toString() {
return '123';
},
valueOf() {
return {};
},
};
console.log(Number(obj)); // 123

对于一些特殊值,Number 类型转换的结果如下:

console.log(Number(undefined)); // NaN
console.log(Number(null)); // 0

使用对应原型上的方法

在隐式类型转换过程中,实际上是调用了对应类型原型上的方法。例如:

console.log(String([])); // ""
// 调用方法: Array.prototype.toString([]);

等效的显式和隐式转换

一些显式和隐式类型转换是等效的,例如:

console.log(String([1, 2])); // "1,2"
console.log('' + [1, 2]); // "1,2"

console.log(String({})); // "[object Object]"
console.log('' + {}); // "[object Object]"

对于函数,toString 方法返回函数的源码字符串表示:

function test() {
console.log(1);
}
console.log(test.toString() === String(test)); // true

函数执行和实例对象

在函数调用和实例化对象时,typeof 运算符的结果会有所不同:

console.log(typeof Date()); // "string"
console.log(typeof new Date()); // "object"

Number 和进制

Number 函数可以将不同进制的数字转换为十进制:

console.log(Number(11)); // 11
console.log(Number(001)); // 1
console.log(Number(0x11)); // 17

Number 函数的作用是将值转换为数字类型:

console.log(Number('123')); // 123
console.log(Number(' 123')); // 123
console.log(Number('.123')); // 0.123
console.log(Number('aaa')); // NaN
console.log(Number('123avs')); // NaN
console.log(Number('1 2 3')); // NaN

parseInt 函数

parseInt 函数用于将字符串转换为整数。它支持不同的进制,进制范围为 2 到 36。

console.log(parseInt('-123abc')); // -123
console.log(parseInt('111', 2)); // 7
console.log(parseInt('111', 6)); // 43
console.log(parseInt('111', 8)); // 73
console.log(parseInt('111', 10)); // 111
console.log(parseInt('111', 16)); // 273
console.log(parseInt('.123')); // NaN
console.log(parseInt('aaa')); // NaN
console.log(parseInt('123avs')); // 123
console.log(parseInt('1 2 3')); // 1

如果需要转换浮点数,可以使用 parseFloat 函数。

null 和 undefined

在相等运算符中,null 和 undefined 是特例。它们在进行隐式类型转换时,行为与其他值不同。

console.log([1] == 1); // true
console.log(['1'] == true); // true
console.log([] == false); // true

console.log([] == null); // false
console.log([] == undefined); // false
console.log([1, 2] == NaN); // false

引用值的比较

在进行引用值的比较时,需要注意一些特殊情况:

console.log(![]); // false
console.log(Number([])); // 0
console.log([] == ![]); // true

对于空数组 [],![] 的结果为 false。将 [] 转换为数字时,结果为 0。因此,[] == ![] 的结果为 true。

console.log(Number({})); // NaN
console.log(!{}); // false
console.log({} == !{}); // false

对于空对象 ,Number() 的结果为 NaN,! 的结果为 false。因此, == ! 的结果为 false。