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

311 阅读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-0NaNnullundefined 和显式的false)会被视为false,而其他所有值则为true

隐式转换: 在隐式转换中,如果参与字符串拼接,那么就是"true""false"字符串。如果参与计算,true1false0

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. 布尔值falsetrue分别转换为01
  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是根据二进制的前三位来判断数据类型的,nullobject的前三位都是000
  4. parseInt()函数用于将字符串解析为整数,遇到非数字字符时停止解析。parseInt()可以有两个参数 第二个参数是 按进制数转化。在例子中,parseInt默认使用了map的第二个参数作为自己的参数(下标)
  5. 还有一点需要注意的是,在使用new创建实例之后,该实例会是一个对象。

结语

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

IP-C.jpg