Skip to main content

类型转换

面试题:该知识点常在笔试题中见到,熟悉了转换规则就不惧怕此类题目了

在 JS 中类型转换只有三种情况,分别是:

  • 转换为布尔值
  • 转换为数字
  • 转换为字符串

另外对箭头函数使用 bind 这类函数是无效的。

转 Boolean

在条件判断时,除了 undefinednullfalseNaN''0-0,其他所有值都转为 true,包括所有对象(空对象,空数组也转为真)。

对象转原始类型

对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数,对于该函数来说,算法逻辑一般来说如下:

  • 如果已经是原始类型了,那就不需要转换了
  • 调用 x.valueOf(),如果转换为基础类型,就返回转换的值
  • 调用 x.toString(),如果转换为基础类型,就返回转换的值
  • 如果都没有返回原始类型,就会报错

当然你也可以重写 Symbol.toPrimitive ,该方法在转原始类型时调用优先级最高。

Symbol.toPrimitive 指将被调用的指定函数值的属性转换为相对应的原始值。

let a = {
valueOf() {
return 0
},
toString() {
return '1'
},
[Symbol.toPrimitive]() {
return 2
}
}
1 + a // 3
"1".concat(a); // "12"

比较运算符

  1. 如果是对象,就通过 toPrimitive 转换对象
  2. 如果是字符串,就通过 unicode 字符索引来比较
let a = {
valueOf() {
return 0
},
toString() {
return '1'
}
}
a > -1 // true

在以上代码中,因为 a 是对象,所以会通过 valueOf 转换为原始类型再比较值。

四则运算符

加法运算符不同于其他几个运算符,它有以下几个特点:

  • 运算中其中一方为字符串,那么就会把另一方也转换为字符串
  • 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
1 + '1' // '11'
true + true // 2
4 + [1,2,3] // "41,2,3"

如果你对于答案有疑问的话,请看解析:

  • 对于第一行代码来说,触发特点一,所以将数字 1 转换为字符串,得到结果 '11'
  • 对于第二行代码来说,触发特点二,所以将 true 转为数字 1
  • 对于第三行代码来说,触发特点二,所以将数组通过 toString 转为字符串 1,2,3,得到结果 41,2,3

另外对于加法还需要注意这个表达式 'a' + + 'b'

'a' + + 'b' // -> "aNaN"

因为 + 'b' 等于 NaN,所以结果为 "aNaN",你可能也会在一些代码中看到过 + '1' 的形式来快速获取 number 类型。

那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字

4 * '3' // 12
4 * [] // 0
4 * [1, 2] // NaN

JS 类型转换规则总结

JS 隐射类型转换

{} 等于 true 还是 false

var a = {};

a == true; // -> false
a == false; // -> false

if (a) {
console.log("进来"); // 会输出
}

因为 a.toString() -> '[object Object]'

100 + 问题

"100" + 100; // "100100"

100 + "100"; // "100100"

100 + true; // 101

100 + false; // 100

100 + undefined; //NaN

100 + null; // 100

parseInt 的坑

parseInt(0.0000001); // 1
parseInt("0.0000001"); // 0
parseInt(1000000000000000000000) // 1
parseInt("1000000000000000000000") // 1e+21

0.0000001.toString(); // "1e-7"

1 与 Number(1)有什么区别

var a = Number(1); // 1
var b = new Number(1); // Number {[[PrimitiveValue]]: 1}
typeof a; // number
typeof b; // object
a == b; // true
  • var a = 1 是一个常量,而 Number(1)是一个函数
  • new Number(1)返回的是一个对象
  • a == b 为 true 是因为所以在求值过程中,总是会强制转为原始数据类型而非对象,例如下面的代码:
typeof 123; // "number"
typeof new Number(123); // "object"
123 instanceof Number // false
(new Number(123)) instanceof Number; // true
123 === new Number(123); // false

console.log(!!(new Boolean(false))输出什么 [易混淆]

true 布尔的包装对象 Boolean 的对象实例,对象只有在 null 与 undefined 时,才会认定为布尔的 false 值,布尔包装对象本身是个对象,对象->布尔 都是 true,所以 new Boolean(false)其实是布尔的 true,看下面这段代码:

if (new Boolean(false)) {
alert("true!!");
}

只有使用了 valueOf 后才是真正的转换布尔值,与上面包装对象与原始资料转换说明的相同:

!!new Boolean(false) //true
(new Boolean(false)).valueOf(); //false

Object.prototype.toString

如果是原始类型,他会将原始类型包装为引用类型,然后调用对应方法

function dd() {}
var toString = Object.prototype.toString;
toString.call(dd); //[object Function]
toString.call(new Object()); //[object Object]
toString.call(new Array()); //[object Array]
toString.call(new Date()); //[object Date]
toString.call(new String()); //[object String]
toString.call(Math); //[object Math]
toString.call(undefined); //[object Undefined]
toString.call(null); //[object Null]
toString.call(123); //[object Number]
toString.call("abc"); //[object String]

obj.toString() 和 Object.prototype.toString.call(obj)

同样是检测对象 obj 调用 toString 方法,obj.toString()的结果和 Object.prototype.toString.call(obj)的结果不一样,这是为什么?

这是因为 toString 为 Object 的原型方法,而 Array ,function 等类型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array 类型返回元素组成的字符串.....),而不会去调用 Object 上原型 toString 方法(返回对象的具体类型),所以采用 obj.toString()不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用 Object 上原型 toString 方法。

输出以下代码运行结果

1 + "1"
2 * "2"
[1, 2] + [2, 1]
"a" + + "b"
  • 1 + "1"
    • 加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来
    • 所以值为:“11”
  • 2 * "2"
    • 乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值
  • [1, 2] + [2, 1]
    • Javascript 中所有对象基本都是先调用 valueOf 方法,如果不是数值,再调用 toString 方法。
    • 所以两个数组对象的 toString 方法相加,值为:"1,22,1"
  • "a" + + "b"
    • 后边的“+”将作为一元操作符,如果操作数是字符串,将调用 Number 方法将该操作数转为数值,如果操作数无法转为数值,则为 NaN。
    • 所以值为:"aNaN"