一条命无伤通关JS面试常考难题:类型转换!!!

390 阅读6分钟

引言

众所周知,ES6之后 JS 有Number、String、Boolean、Null、Undefined、Symbol、BigInt、Object这几种数据类型。这篇文章将带你一遍梳理各种数据类型之间的显隐式转换情况。

0c6c0064ef8b27dab56776daba719400d58471b6.jpg

弱类型语言

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()构造函数可以用来将各种类型的值转换为数字。

  1. 对于无法解析为有效数字的字符串,结果将是NaN。
  2. 对于没有参数、null、空字符串""或仅包含空白字符的字符串" ",结果是0。
  3. 布尔值false和true分别转换为0和1。
  4. 对于可以解析成数字的字符串,结果为解析后的数字。

隐式转换:

  1. 当加号 (+) 两边的操作数都明确为数字时,它执行数值相加。当至少有一个操作数是字符串,或者当操作数被转换为字符串时,它执行字符串拼接。
  2. 其他运算符号 (-,*,/,%) ,当至少有一个操作数不是数字时,非数字操作数会被尝试转换为数值。如果转换失败,结果将是 NaN。
  3. 严格相等操作符 === 不会进行隐式转换。

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);
}

总结

显示转换:

  1. 如果 BigInt 表示的数值超出了 Number 类型的安全整数范围,那么转换后的结果可能不准确。
  2. 转换为字符串时会返回Symbol(a)。不能直接将 Symbol 转换为数字。如果尝试这样做,会导致抛出 TypeError 错误。

隐式转换:

  1. 在大多数情况下,BigInt 不会隐式转换为其他类型。但在与字符串拼接时,BigInt 会被自动转换为字符串。
  2. 当试图将 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
  1. 在编程中,我们往往会忽视掉+0和-0在数学上的区别。尽管它们通常表现相同,但在除法中,1/+0会得到Infinity,而1/-0则返回-Infinity(虽然在数学中0并不能做分母)。Object.is()函数可以区分这两种不同的零。
  2. NaN(Not a Number)也是一种特殊的数字,用于表示未定义或不可表示的值。根据 IEEE 754 浮点数标准,NaN 不等于任何东西,包括它自己。正确的方法是使用isNaN()函数来判断是否为NaN。
  3. null使用typeof会显示出object,因为typeof是根据二进制的前三位来判断数据类型的,null和object的前三位都是000。
  4. parseInt()函数用于将字符串解析为整数,遇到非数字字符时停止解析。parseInt()可以有两个参数 第二个参数是 按进制数转化。在例子中,parseInt默认使用了map的第二个参数作为自己的参数(下标)
  5. 还有一点需要注意的是,在使用new创建实例之后,该实例会是一个对象。

结语

希望本文能为你的 JS 的类型转换学习提供有价值的帮助,欢迎大家帮助我补充。

IP-C.jpg