JS-类型转换

两种转换形式:显式类型转换隐式类型转换

三种转换结果:数字布尔值字符串

1. 显式类型转换

常见的显式类型转换有构造函数形式Number()、String()、Boolean(),和new一个实例不一样哦

const a = new Number('123'); // a === 123 is false 
const b = Number('123');     // b === 123 is true 
a instanceof Number;         // is true 
b instanceof Number;         // is false

基本类型转数字

  • Number()

    直接上规范:如果传入参数,调用底层函数ToNumber(),如果未传入参数,返回+0

    在这里插入图片描述

    而调用底层函数ToNumber()有如下结果

    参数类型 结果
    Undefined NaN
    Null +0
    Boolean true返回1false返回**+0**
    Number 就是输入的参数了
    String 情况比较复杂

    String的说明

    • 如果字符串中只包含数字**(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1" 会变成 1,"123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了)**;
    • 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零);
    • 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整数值;
    • 如果字符串是空的(不包含任何字符),则将其转换为0;
    • 如果字符串中包含除上述格式之外的字符,则将其转换为NaN。
    console.log(Number("123")) // 123
    console.log(Number("-123")) // -123
    console.log(Number("1.2")) // 1.2
    console.log(Number("000123")) // 123
    console.log(Number("-000123")) // -123
    
    console.log(Number("0x11")) // 17
    
    console.log(Number("")) // 0
    console.log(Number(" ")) // 0
    
    console.log(Number("123 123")) // NaN
    console.log(Number("foo")) // NaN
    console.log(Number("100a")) // NaN
    
  • parseInt()和parseFloat()

    这两个是针对字符串转数字的情况,因为用Number()转字符串的时候,复杂又不合理

    • parseInt()针对整数

      • 忽略前导空格,第一个不为空的字符如果不是数字/正负号,就返回NaN;

      • 解析后续字符直到遇到不是数字的字符,后面的字符全部忽略,返回之前的数字

        parseInt('  +3')     //+3
        parseInt('')         //空字符串,NaN
        parseInt(' ')        //NaN
        parseInt('*12')      //NaN
        parseInt('123blue')  //123
        parseInt(2.25)       //2,'.'不是数字,小数点后面都被忽略了
        parseInt('0xf')      //15,十六进制
        parseInt('070')      //70,八进制,但是ES5认为这是70
        
      • 第二个参数可以指定进制

        parseInt('070',8)  //56
        
    • parseFloat(针对浮点数)

      • 只解析十进制

      • 忽略前导0和空格,第一个不为空的字符如果不是数字/正负号,就返回NaN;

      • 解析后续字符,第一次遇到小数点有效,第二次就无效了,其他非数字字符第一次就无效,返回前面的数字

        console.log(parseFloat('  +3'));    //3
        console.log(parseFloat('  -3'));    //3
        console.log(parseFloat(''));        //NaN
        console.log(parseFloat(' '));       //NaN
        console.log(parseFloat('*12'));     //NaN
        console.log(parseFloat('123blue')); //123
        console.log(parseFloat(2.25));      //2.25
        console.log(parseFloat('2.25.4'));  //2.25
        console.log(parseFloat('0xf'));     //0,遇到十六进制都是0
        console.log(parseFloat('070'));     //70
        

基本类型转字符串

  • String()

    还是上规范:如果传入参数就调用底层函数ToString(),否则返回空字符串
    在这里插入图片描述

    ToString()结果如下

    参数类型 结果
    Undefined "undefined"
    Null "null"
    Boolean true返回**“true”,false返回"false"**
    Number 情况比较复杂
    String 没转换

    Number的说明

    • NaN,转换为"NaN"
    • +0/-0,转换为"0"
    • Infinity,转换为"Infinity"
    • 会进制转换
    console.log(String(NaN));         //"NaN"
    console.log(String(-0));          //"0"
    console.log(String(+0));          //"0"
    console.log(String(-Infinity));   //"-Infinity"
    console.log(String(Infinity));    //"Infinity"
    console.log(String(0xf));         //"15"
    console.log(String(070));         //"56"
    
  • toString()

    Boolean、Number、String是基本包装类型,有toString方法

    null和undefined没有toString方法,所以没法转换

    转换规则和ToString是一样的

    console.log((-0).toString());         //0
    console.log((NaN).toString());        //'NaN'
    console.log((0xf).toString());        //'15'
    console.log((070).toString());        //'56'
    console.log((-Infinity).toString());  //'-Infinity'
    

基本数据类型转布尔值

  • Boolean()

    情况就没有那么复杂了,有6种值会被转换为false,其余均为true

    //以下都是false
    console.log(Boolean());
    console.log(Boolean(false));
    console.log(Boolean(undefined));
    console.log(Boolean(null));
    console.log(Boolean(NaN));
    console.log(Boolean(''));
    console.log(Boolean(-0));
    console.log(Boolean(+0));
    console.log(Boolean(0));
    
    console.log(Boolean(' '));  //true
    

对象转数字/字符串

  • ToPrimitive()

    基本类型转数字的时候就介绍了底层函数ToNumber(),给出的表格其实缺少了参数为对象时的情况,现在这里补上

    参数类型 结果
    Object 1. primValue = ToPrimitive(input, Number) 2. 返回ToNumber(primValue).

    另一个底层函数ToString(),对于参数为对象有类似的处理

    参数类型 结果
    Object 1. primValue = ToPrimitive(input, String) 2. 返回ToString(primValue).

    这里引入了另一个底层函数ToPrimitive(input,preferredType)—把输入转换为初始值,这个函数调用结果如下

    参数类型 结果
    基本数据类型 本身
    Object blablabla一大堆,咱也没看懂,下面介绍好理解的处理方式

    Object情况的说明:

    • preferredType == Number

      • 调用valueOf(),结果为初始值就返回,否则下一步
      • 调用toString(),结果为初始值就返回,否则下一步
      • 抛出错误
    • preferredType == String

      • 调用toString(),结果为初始值就返回,否则下一步
      • 调用valueOf(),结果为初始值就返回,否则下一步
      • 抛出错误
  • toString()和valueOf()

    • toString()

      上面介绍基本数据类型转字符串的时候,介绍了这个方法,那么对象用这个方法呢?

      var a = [1,2,3]
      var b = {val:4}
      var c = function(x){
        return x++
      }
      var d = new Date()
      var e = /\d+/g
      
      console.log(a.toString());  //'1,2,3'
      console.log(b.toString());  //"[object object]"
      console.log(c.toString());  //'function(x){ return x++ }'
      console.log(d.toString());  //Thu Apr 09 2020 17:55:26 GMT+0800 (中国标准时间)
      console.log(e.toString());  ///\d+/g
      
    • valueOf()

      无论是哪种数据类型,返回参数本身,类型也不会变化,唯一特殊的是Date对象

      var date = new Date()
      console.log(date.valueOf());  //1586426466217,1970.1.1距今的毫秒数
      

      另外包装类型Number、String、Boolean,也是Object类,用valueOf后类型转换为基本数据类型

      var c = new Number(12)
      console.log(c instanceof Number);  //true
      console.log(c instanceof Object);  //true
      console.log(c.valueOf());          //12
      console.log(typeof c.valueOf());   //Number
      
  • 转数字Number()

    根据上面的分析,我们可以得出对象转数字的过程了

    • 有**valueOf()**方法,就用,结果为基本数据类型就返回,否则下一步
    • 有**toString()**方法,就用,结果为基本数据类型就返回,否则报错
    • 得到基本数据类型primValue后,调用ToNumber(primValue),下面就很熟悉了
    console.log(Number([1,2,3]));  //NaN
    console.log(Number([]));       //0
    console.log(Number([0]));      //0
    console.log(Number({val:4}));  //NaN
    console.log(Number({}));       //NaN
    console.log(Number(function(x){ return x++ })); //NaN
    console.log(Number(new Date()));
    console.log(Number(/\d+/g));   //NaN
    

    试着分析[]和[1,2,3]的情况

    [].valueOf() == [],不是基本数据类型
    [].toString() == '',是基本数据类型
    ToString('') == 0
    
    [1,2,3].valueOf() == [1,2,3],不是基本数据类型
    [1,2,3].toString() == '1,2,3',是基本数据类型
    ToString('1,2,3') == NaN
    
  • 转字符串

    参考转数字的过程,有

    • 有**toString()**方法,就用,结果为基本数据类型就返回,否则下一步
    • 有**valueOf()**方法,就用,结果为基本数据类型就返回,否则报错
    • 得到基本数据类型primValue后,调用ToString(primValue),下面就很熟悉了
    console.log(String([1,2,3]));    //'1,2,3'
    console.log(String([]));         //一个空格
    console.log(String([0]));        //'0'
    console.log(String({val:4}));    //'[object Object]'
    console.log(String({}));         //'[object Object]'
    console.log(String(function(x){ return x++ }));  //'function(x){ return x++ }'
    console.log(String(new Date())); //'Thu Apr 09 2020 19:23:31 GMT+0800 (中国标准时间)'
    console.log(String(/\d+/g));     //'/\d+/g'
    

对象转布尔值

都转为true!包装类型也是!

2.隐式类型转换

最常见的就是运算符+、==或者if语句中的条件判断,其实还有比较运算符、自增++、自减–等等

一元运算符+a

调用ToNumber(),对+后面的数据进行转换,那么这个就很熟悉了

//基本数据类型
console.log(+'12.3');    //12.3
console.log(+'-12.3');   //-12.3
console.log(+'');        //0
console.log(+true);      //1
console.log(+null);      //+0
console.log(+undefined); //NaN

//对象
console.log(+[]);        //0
console.log(+[ ]);       //0
console.log(+[1]);       //1
console.log(+[1,2]);     //NaN
console.log(+{});        //NaN
console.log(+{val: 'happy'}); //NaN
console.log(+new Date());     //1586433193168,1970.1.1距今毫秒数

二元运算符a+b

看规范吧

  • left = ToPrimitive(a),right = ToPrimitive(b),a和b是基本数据类型的话,left = a,right = b

  • 如果上述两个值有一个是字符串ToString(left)拼接ToString(right)

  • 否则ToNumber(left)加上ToNumber(right)

两个数字相加遵循以下规则

  • 如果有一个操作数是 NaN,则结果是 NaN;
  • Infinity + Infinity = Infinity;
  • (-Infinity) + (-Infinity )= -Infinity;
  • Infinity + (-Infinity) = NaN;
  • (+0) + (+0) = +0;
  • (-0) +(-0) = -0;
  • (+0) + (-0) = +0。
console.log('1'+123);  //'1123'
console.log(null+1);   //1,两个都不是字符串,所以null转换为0,和1相加
console.log([]+[]);    //'',经过ToPrimitive得到''+'' = ''
console.log(['1']+1);  //'11',经过ToPrimitive得到'1'+1 = '11'
console.log([]+{});    //'[object Object]',经过ToPrimitive得到''+'[object Object]'

比较运算符a==b和a!=b

还是规范,看吐了,11.9.3,这里给出精简版的

  • 有一个为 NaN,则返回 false;
  • a∈{null,undefined}且b∈{null,undefined},返回true,有一个不属于{null,undefined},返回false
  • 如果a和b类型不一致
    • a和b为 String、Number、Boolean 中的某一类型,则使用 ToNumber 函数转化为 Number 类型再进行比较;
    • 有一个是Object,另一个是 String、Number、Boolean 中的某一类型,则ToPrimitive(Object)转换为基础数据类型,再按照上一步比较
  • 相同类型,就好比较了
//规则1,全部是false
console.log(NaN == NaN); 
console.log(null == NaN); 
console.log(undefined == NaN);

//规则2
console.log(null == null);           //true
console.log(undefined == undefined); //true    
console.log(null == {});             //false

//规则3.1
console.log(1 == true);    //true
console.log('1' == true);  //true
console.log(0 == false);   //true
console.log('1' == 1);     //true

//规则3.2
console.log({} == {});    
console.log([] == false);   //true
console.log([0] == 0);      //true
console.log(['0'] == 0);    //true

//规则4
console.log([0] == ['0']);  //false,这个脑子瓦特了,肯定false
console.log(+0 == 0);       //true
console.log(-0 == 0);       //true
console.log(+0 == -0);      //true

你可能感兴趣的:(JS-类型转换)