logo头像
Snippet 博客主题

js隐式类型转换学习总结

本文于986天之前发表,文中内容可能已经过时。

为什么会写这篇博客,因为自己类型转换规则实在记不住,直接先看练习题,都没问题就直接pass。

前置知识点:

  • js基本数据类型比较的是值是否相等
  • js引用数据类型比较的是引用的地址是否相等
  • ==比较会进行类型转换,===必须类型相同值也相等

==比较类型转换规则:

  • 首先排除特殊的nullundefined类型:

    1
    2
    3
    null ==  undefined; // true
    0 == undefined; // false
    0 == null; // false
  • 比较双方的类型相同,则进行值的判断:

    1
    [] ==  []; // false(类型相同但引用的地址不同)
  • 比较双方的类型不同,进行类型转换,规则如下:

    • 若其中一方为object且另一方为stringnumber或者symbol, 将object转为基本类型再进行判断

      1
      2
      3
      4
      [] ==  ''; // true
      [] == 0; // true
      [null] == 0; // true
      [undefined] == 0; // true
    • 若其中一方为boolean, 将boolean转为number再进行判断

      1
      2
      true ==  1; // true
      false == 0; // true
    • 若双方类型为stringnumber, 将string转换成number

      1
      '12' ==  12; // true

object转换成基本类型规则:

object这种复杂类型转换成基本类型时,会调用对象的valueOftoString方法。

1
2
3
4
{}.toString(); // '[object Object]'
[1,2,3].valueOf(); // [1,2,3]
[1,2,3].toString(); // '1,2,3'
Object.prototype.toString.call([1,2,3]); // '[object Array]' (可判断是否为数组)

valueOftoString方法调用顺序:

  1. 若显示定义了[Symbol.toPrimitive]属性,只调用该接口,若返回的不是基本数据类型,抛出错误。
  2. 默认的调用规则:
    • Date类型对象,hintdefault时,调用顺序为:valueOf >>> toString,即valueOf返回的不是基本数据类型,才会继续调用toString,如果toString返回的还不是基本数据类型,那么抛出错误。
    • 如果hintstring(Date对象默人的hint是string) ,调用顺序为:toString >>> valueOf,即toString返回的不是基本数据类型,才会继续调用valueOf,如果valueOf返回的还不是基本数据类型,那么抛出错误。
    • 如果hintnumber,调用顺序为:valueOf >>> toString
1
2
(new Date()).toString(); // 'Sun Jun 30 2019 16:53:46 GMT+0800 (中国标准时间)'
(new Date()).valueOf(); // 1561884790571

关于hint, [Symbol.toPrimitive]示例可访问上文引用链接
关于[Symbol.toPrimitive]可参考:- 阮一峰·ECMAScript 6 入门

string转换成number规则:

Number()parseInt()方法

1
2
3
4
Number('12abc'); // NaN
Number(undefined); // NaN
Number(null); // 0
parseInt('12abc'); // 12

parseInt()经典面试题

String()toString()方法

1
2
3
4
undefined.toString(); // TypeError: Cannot read property 'toString' of undefined
null.toString(); // TypeError: Cannot read property 'toString' of null
String(undefined); // 'undefined'
String(null); // 'null'

radix为2时,NumberObject会被转换为二进制值表示的字符串

1
2
var num = 13;
console.log(num.toString(2));

typeof判断类型:

typeof方法返回值:undefined, boolean, number, string, symbol, function, object

1
2
3
4
5
6
7
8
typeof null; // 'object'
typeof [1,2,3]; // 'object'
typeof new Boolean(true); // 'object'
typeof new Number(1); // 'object'
typeof new String("abc"); // 'object'
typeof NaN; // 'number'
typeof (typeof 1); // 'string'
typeof undefined; // 'undefined'

练习题

  1. []开辟了一块堆内存,地址存在栈内存,![]返回false

    1
    2
    3
    if ([]) {
    ... // true
    }
  2. 比较双方的类型相同,则进行值的判断,栈内存地址不同

    1
    2
    [] == []; // false
    {} == {}; // false
  3. 解题参考:- 【面试篇】寒冬求职季之你必须要懂的原生JS(上)

    1
    2
    3
    [] == ![] // true
    {} == !{} // false
    {} == '[object Object]' // true

疑惑:文中最后一步Number([])确实为0,但是和object转换成基本类型规则:似乎有冲突。

  1. 运算符进行隐式类型转换
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    '12' + 1; // '121'(String)
    1 + 'true'; // '1true'
    1 + true; // 2
    1 + undefined; // NaN
    1 + null; // 1
    '12' * 1; // 12(Number)
    '12' - 1; // 11(Number)
    'a' - 1; // NaN
    2 > '10'; //false
    '2' > '10'; // true
    'abc' > 'b'; // false
    'abc' > 'aad'; // true
    [] + {}; // '[object Object]'
    [] + []; // ''
  • 字符串连接符+:只要+号两边有一边是字符串
  • 算术运算符++号两边都是数字
  1. 特殊类型比较null, undefined, NaN的比较

    1
    2
    3
    undefined == null; // true
    NaN == NaN; // false
    NaN == null; // false
  2. Can (a== 1 && a ==2 && a==3) ever evaluate to true?

    1
    2
    3
    if (a == 1 && a == 2 && a == 3) {
    // ...
    }

解答:

  • 利用数组的toString会隐含调用Array.join方法
1
2
3
a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);
  • 重写ObjecttoString或者valueOf
1
2
3
4
5
6
7
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
console.log(a == 1 && a == 2 && a == 3);

参考文章:

微信打赏

赞赏是不耍流氓的鼓励