引言
众所周知,ES6之后 JS 有Number、String、Boolean、Null、Undefined、Symbol、BigInt、Object这几种数据类型。这篇文章将带你一遍梳理各种数据类型之间的显隐式转换情况。
弱类型语言
JS 被称为弱类型(或动态类型)语言,这意味着在 JS 中变量不需要显式声明其类型,并且可以在程序运行时改变它们所持有的值的类型。所以说,JS 的变量在定义时是 undefined ,只有确切的给定了一个值,它才会根据值来变化它的数据类型。
var a
console.log(typeof a); // undefined
a = "1";
console.log(typeof a); // String
a = Number("1");
console.log(typeof a); // Number
a = true
console.log(typeof a); // Boolean
Boolean类型转换
通过Boolean(布尔值)能够进行逻辑判断,布尔值只有两个值:true、fasle。我们直接通过例子来总结它的类型转换机制。
// false | true
// Primitive -> Boolean
// 构造函数 来用
// 显示转换
console.log(Boolean()); // 默认值为 false
console.log(Boolean(false)); // false
console.log(Boolean(true)); // true
console.log(Boolean(undefined)); // false
console.log(Boolean(null)); // false
console.log(Boolean(+0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean('')); // false
// 隐式转换
console.log(true + false); // 1 计算
console.log(true + '1'); // true1
console.log(false + '1'); // false1
console.log(true * 1); // 1
console.log(false / 1); // 0
console.log(true == 1); // true
console.log(false == 0); // true
console.log(true === 1); // false
console.log(false === 0); // false
总结
显式转换: 某些特定值(如空字符串 ""、+0、-0、NaN、null、undefined 和显式的false)会被视为false,而其他所有值则为true。
隐式转换: 在隐式转换中,如果参与字符串拼接,那么就是"true"和"false"字符串。如果参与计算,true为1,false为0。
Number类型转换
// 显式转换
console.log(Number()); // 0
console.log(Number(undefined)); // NaN
console.log(Number(null)); // 0
console.log(Number(false)); // 0
console.log(Number(true)); // 1
console.log(Number("123")); // 123
console.log(Number("-123")); // -123
console.log(Number("0x11")); // 17 (支持十六进制转换)
console.log(Number(""), Number(" ")); // 0, 0
console.log(Number("100a")); // NaN
// 隐式转换
console.log(2 * "a",2 + "a",2 * "2"); // NaN 2a 4
console.log(+"1"); // 1
console.log("10" == 10); // true
console.log("10" === 10); // false
console.log(typeof NaN); // number
总结
显式转换:Number()构造函数可以用来将各种类型的值转换为数字。
- 对于无法解析为有效数字的字符串,结果将是
NaN。 - 对于
没有参数、null、空字符串""或仅包含空白字符的字符串" ",结果是0。 - 布尔值
false和true分别转换为0和1。 - 对于可以解析成数字的字符串,结果为解析后的数字。
隐式转换:
- 当加号 (
+) 两边的操作数都明确为数字时,它执行数值相加。当至少有一个操作数是字符串,或者当操作数被转换为字符串时,它执行字符串拼接。 - 其他运算符号 (
-,*,/,%) ,当至少有一个操作数不是数字时,非数字操作数会被尝试转换为数值。如果转换失败,结果将是NaN。 - 严格相等操作符
===不会进行隐式转换。
String类型转换
// 显式转换
console.log(String()); // ""
console.log(String(undefined), typeof String(undefined));
// "undefined" "string"
console.log(String(null), typeof String(null)); // "null" "string"
console.log(String(+0), String(-0)); // "0" "0"
console.log(String(NaN)); // "NaN"
console.log(String(+1)); // "1"
// 隐式转换(常见的隐式转换已经在前面的内容中讲到了,下面是一些你平常可能不会注意的部分)
alert(42); // 显示对话框,内容为 "42"
console.log(true); // 输出 "true"
总结
显式转换:相比之下,String()就感觉要强大的多,它几乎把所有类型的值都直接转为了字符串,并且结果非常直观。null就是"null",undefined就是"undefined"等等。但有一点要注意的是,+0,-0的结果都是0,正数转为字符串的时候+会被省略掉。
隐式转换:当传递给 alert() 或 console.log() 的参数不是字符串时,它们会被隐式转换为字符串。
BigInt 和 Symbol
//BigInt
let bigInt = 1234567890123456789012345678901234567890n;
// 如果 BigInt 超出了 Number 安全整数范围, 转换后可能丢失精度
console.log(Number(bigInt));
console.log(String(bigInt)); // "1234567890123456789012345678901234567890"
console.log("The value is " + bigInt);
// "The value is 1234567890123456789012345678901234567890"
//Symbol
let sym = Symbol('a');
console.log(String(sym)); // "Symbol(a)"
// 尝试将 Symbol 转换为数字会失败
try {
console.log(Number(sym)); // 抛出 TypeError
} catch (e) {
console.error(e);
}
总结
显示转换:
- 如果
BigInt表示的数值超出了Number类型的安全整数范围,那么转换后的结果可能不准确。 - 转换为字符串时会返回
Symbol(a)。不能直接将Symbol转换为数字。如果尝试这样做,会导致抛出TypeError错误。
隐式转换:
- 在大多数情况下,
BigInt不会隐式转换为其他类型。但在与字符串拼接时,BigInt会被自动转换为字符串。 - 当试图将
Symbol隐式转换为其他类型时,比如在加法运算中与字符串相加或者作为对象属性名使用,JS 会自动调用symbol.toString()方法来获取其字符串表示形式。在数值上下文中使用Symbol会导致错误,因为Symbol没有定义如何转换成数值。
特殊数值处理
console.log(1/+0); // Infinity 无穷大
console.log(1/-0); // -Infinity
console.log(Object.is(5,5)); // true
console.log(Object.is(+0,-0)); // false
console.log(typeof NaN); // "number"
console.log(NaN === NaN); // false
console.log(isNaN(), isNaN(parseInt("abc"))); // true, true
console.log(typeof null); // "object"
console.log(parseInt("abc")); // NaN
console.log(parseInt("12abc")); // 12
console.log([1,2,3].map(parseInt)); // 1 NaN NaN
// parseInt(1,0) 第二个参数为0或者未提供 会根据字符串的内容自动推断应该使用的进制
// parseInt(2,1) 第二个参数应为(2~36)之间的整数 NaN
// parseInt(3,2) 二进制 二进制没有 3 NaN
var a = 1.234;
console.log(typeof a,a.toFixed(2)); // number 1.23
var b = new Number(a); // 使用new之后 类型会变为Object
console.log(typeof b); // object
console.log(b.toFixed(2)); // 1.23
- 在编程中,我们往往会忽视掉
+0和-0在数学上的区别。尽管它们通常表现相同,但在除法中,1/+0会得到Infinity,而1/-0则返回-Infinity(虽然在数学中0并不能做分母)。Object.is()函数可以区分这两种不同的零。 NaN(Not a Number)也是一种特殊的数字,用于表示未定义或不可表示的值。根据 IEEE 754 浮点数标准,NaN不等于任何东西,包括它自己。正确的方法是使用isNaN()函数来判断是否为NaN。null使用typeof会显示出object,因为typeof是根据二进制的前三位来判断数据类型的,null和object的前三位都是000。parseInt()函数用于将字符串解析为整数,遇到非数字字符时停止解析。parseInt()可以有两个参数 第二个参数是 按进制数转化。在例子中,parseInt默认使用了map的第二个参数作为自己的参数(下标)- 还有一点需要注意的是,在使用
new创建实例之后,该实例会是一个对象。
结语
希望本文能为你的 JS 的类型转换学习提供有价值的帮助,欢迎大家帮助我补充。