JS隐式/强制 数据类型转换

350 阅读6分钟

强制类型转换

(1)布尔值转换

Boolean类型只有两个字面值:true和false。

0-0NaNundefinednull""(空字符串)这几种情况转换布尔类型会得到 false,除了这几种情况外所有数据类型都会得到 true。

(2)数值类型转换

由以下三种强制类型转换:

  • Number():属于严格转换

  • 当全部为数字或者解析全部为数字时才会正确转换。

  • 当出现非数字或者空格时返回NaN,

  • 当遇到空字符串、null或者布尔类型false时返回0,

  • 当遇到布尔类型true时返回1,

  • 当遇到undefined时返回NaN。

isNaN(): 可以用于判断传入值是否为非有效数字,非有效数字返回true有效数字返回false。

Number.isNaN(): 只有当传入的值未NaN时, 才返回true, 否则返回false

console.log(Number(123));   //123
console.log(Number('123')); //123
console.log(Number('123aa'));   //NaN
console.log(Number(''));   //0
console.log(Number([]));   //0
console.log(Number(null));   //0
console.log(Number(false));   //0
console.log(Number(true));   //1
console.log(Number(undefined));   //NaN
  • parseInt():非严格转换

该方法可以把其他数据类型转换为整数,只取整数部分,当遇到以非数字开头的数据类型时,返回NaN。

console.log(parseInt(123)); //123
console.log(parseInt(123.23)); //123
console.log(parseInt('123.23')); //123
console.log(parseInt('123aa')); //123
console.log(parseInt('.123aa')); //NaN
console.log(parseInt('abc')); //NaN
console.log(parseInt('abc123')); //NaN
  • parseFloat():与parseInt转换机制一样, 只不过该方法是保留浮点数。

    console.log(parseFloat(123)); //123 console.log(parseFloat(123.23)); //123.23 console.log(parseFloat('123.23')); //123.23 console.log(parseFloat('123aa')); //123 console.log(parseFloat('.123aa')); //0.123 console.log(parseFloat('ab123.23aa')); //NaN console.log(parseFloat('abc')); //NaN

(3)字符串转化

  • toString()

几乎每个类型的值都有的toString()。

但是有一点需要注意的是nullundefined值没有这个方法。

var colors = ['red','blue','green'];
var num = 123;
var found = true;
console.log(colors.toString()); //"red,blue,green"
console.log(num.toString());    //"123"
console.log(found.toString());  //"true"
  • String()

这个函数可以将任何值转换为字符串

var colors = ['red','blue','green'];
var num = 123;
var found = true;
console.log(String(colors)); // "red,blue,green"
console.log(String(num));    // "123"
console.log(String(found));  // "true"
console.log(String(null));  // "null"
console.log(String(undefined));  // "undefined"

valueOf和toString的区别

基本上所有的JavaScript数据类型都有valueOf(),toString()方法,null和undefined除外,这两个方法解决了JavaScript值运算和显示的问题。

valueOf():会把数据类型转换成原始类型,也就是说原来是什么类型,转换后还是什么类型,日期类型除外。

toString():会把数据类型转换成string类型,也就是说不管原来是什么类型,转换后一律是string类型。

使用场景

  • valueOf()偏向于运算,toString()偏向于显示
  • 对象转换时,优先调用toString()
  • 强转字符串的情况下,优先调用toString()方法;强转数字的情况下优先调用valueOf()
  • 正常情况下,优先调用toString()
  • 在有运算操作符的情况下valueOf()的优先级高于toString(),这里需要注意的是当调用valueOf()方法无法运算后还是会再调用toString()方法

隐式转换规则

  • 转为number类型+ - * / ++ --(算数运算符) > < >= <= == != === !==(比较运算符);
  • 转为string类型+ 不仅是算术运算符,还可以做为字符串连接符把数据转换成string类型;
  • 转为boolean类型!(逻辑非运算符)

+运算符的隐式转换

+两边有一边是字符串那这个**+**就是字符串连接符,它会把其他数据类型调用String()方法转成字符串然后拼接;

+做为算术运算符会把其他数据类型调用Number()转成数字然后做加法运算;

console.log(1 + true);      //2
console.log(1 + "true");        //"1true"
console.log(1 + undefined);     //NaN
console.log(1 + null);      //1

// null转化为0   undefined转化为NaN

比较(关系)运算符的隐式转化

比较运算符会把其他数据类型转换number数据类型后再比较。

  • 当一边是字符串的时候,会调用 Number() 方法把字符串转换成数字在进行比较;

  • 当关系运算符两边都是字符串的时候,此时同时转成number然后比较关系;

重点:此时并不是按照Number()的形式转成数字,而是按照字符串对应的unicode编码来转成数字,使用 字符串.charCodeAt(字符下标,默认为0) 方法可以查看字符的unicode编码。

  • 当布尔值和数字比较时,会把布尔值通过 Number() 转成数字再进行比较,true转成 1false 转成 0

  • 当字符串和布尔值比较时,会把字符串和布尔值都通过 Number() 转成数字再进行比较。

注:null == undefined //true ; NaN和谁都不相等,包括他自己.

console.log("2" > 10);      //false
console.log("a" > 10);      //false
console.log(10 > "a");      //false
console.log(Number("a"));      //NaN
console.log("2" > "10");        //true '2'.charCodeAt() > '10'.charCodeAt() = 50 > 49 = true
console.log(false == 0);        //true
console.log(false == "");       //true
console.log(Number(false));       //0
console.log(NaN == NaN);        //false
console.log(undefined == null);     //true
console.log(Number(NaN));       //NaN
console.log(Number(undefined));     //NaN
console.log(Number(null))       //0

复杂数据类型的隐式转换

会将复杂数据类型转化为number数据类型, 再进行比较。

  • 先使用 valueOf() 方法获取原始值,如果原始值不是number数据类型,则使用 toString() 方法转成string;
  • 再通过 Number() 方法装成number数据类型

注意:空数组的toString()方法会得到空字符串,而空对象的toString()方法会得到字符串[object Object]

console.log([1,2] == '1,2'); //true  先将左边数组转成string,然后右边也是string则转成unicode编码运算
console.log([] == 0);//true  默认通过同String()转成空字符串,再通过Number("")转成0
var a = {};
console.log(a == 0); //false
console.log(a.valueOf().toString()); //"[object Object]"

逻辑非隐式转换和比较运算符隐式转换

0-0NaNundefinednull""(空字符串)这几种情况转换布尔类型会得到 false除了这几种情况外所有数据类型都会得到 **true。**

以下都是:

  • **先将左右两边的值通过.valueOf().toString()转化为字符串, **
  • 然后通过Number("值")转化为数字之后进行对比。
  //大坑
    console.log ( [] == 0 );        //true
    console.log ( ! [] == 0 );      //true
    //神坑
    console.log ( [] == ! [] );     //true
    console.log ( [] == [] );       //false
    //史诗级坑
    console.log({} == !{});     //false
    console.log({} == {});      //false
`[]` 与 `0`比较:
  • [].valueOf().toString() 得到空字符串
  • Number("") == 0 成立

![]0比较:

  • 逻辑非优先级高于关系运算符 ![] = false (空数组转布尔得到true,然后取反得到false)
  • false == 0 成立

[]![]比较:

  • [].valueOf().toString() 得到空字符串 ""
  • ![] = false
  • Number("") == Number(false) 成立 都是0

[][]比较:
引用类型数据存在堆内存中,栈内存中存储的是地址,所以他们的结果是false
{}!{}比较:

  • {}.valueOf().toString() 得到字符串'[object Object]'
  • !{} = false
  • Number('[object Object]') == Number(false) 不成立,因为转换到最后 是NaN0比较,所以结果为 false

{}{}比较:
引用类型数据存在堆内存中,栈内存中存储的是地址,所以他们的结果是false

参考文章:js数据类型转化

常用的几种运算符各运算符优先级:

算术运算符:+ - * / ++ --
比较运算符: > < >= <= == != === !==
逻辑运算符:&& || !
赋值运算符:= += -= *= /=
算术运算符 > 比较运算符 > 逻辑运算符 > 赋值运算符