类型转换

154 阅读5分钟

1、其他数据类型转换为number类型

把其他数据类型转换为数字的方法

  • 强转换(基于底层机制转换的)Number([value])
    • 隐式转换:浏览器内部默认要先转换为Number再进行计算的
      • isNaN('12px'); 先把其他类型值转换为数字再检测
      • 数学运算 '12'-13;
      • 字符串==数字 两个等号的比较很多时候也是要把其他值转换为数字
  • 弱转换(基于一些额外的方法转换)
    • parseInt([value])
    • parseFloat([value])

转换规律

  • parseInt()处理的值是字符串,从字符串的左侧第一个字符开始查找有效数字字符(遇到非有效数字字符则停止查找)。把找到的有效数字字符转换为数字,如果一个都没找到结果就是NaN。如果处理的值不是字符串,需要先转换为字符串然后再开始查找。

  • Number()直接调用浏览器底层的数据类型检测机制来完成

    • true => 1
    • false => 0
    • null => 0
    • '' => 0
    • undefined => NaN
    • 字符串中必须保证全部是有效数字才会转换为数字,否则都是NaN
  • +号运算符遇到字符串(或者对象,因为对象就是先转换为字符串然后再处理),做拼接处理

举个例子

parseInt(''); // NaN => ''不是有效数字
Number(''); // 0
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN 
Number('12px'); // NaN => 有无效数字,因此结果为NaN
isNaN(''); // false => isNaN使用Number()隐式转换 => isNaN(0),0是有效数字,因此结果为false
parseInt(null); // NaN => parseInt()把里面的值转换为字符 => parseInt('null') => NaN
isNaN(null); // false => isNaN使用Number()隐式转换 => isNaN(0),0是有效数字,因此结果为false
parseInt('12px'); // 12 => 查找有效数字为止,因此结果为12
isNaN('12px'); // true => isNaN使用Number()隐式转换 => isNaN(NaN),因此结果为true
parseFloat('1.6px') + parseInt('1.2px') + typeof parseInt(null); // "2.6number" => 1.6 + 1 + typeof NaN => 因此结果为"2.6number"
typeof !parseInt(null) + isNaN(null); // 'booleanfalse' => typeof !NaN + false => "boolean" + false => 因此结果为'booleanfalse'
[]==true; // false => 都转换为数字 Number([]) => Number('') => 0,因此 0==1为false
![]; // false => 这是个表达式,先把[]转换为布尔值,只有0,空字符串,null,undefined,NaN
转换为布尔值是false,其他都是true,因此!true取反,结果为false
let res = 10 + false + undefined + [] + 'Tencent' + null + true + {};
console.log(res);
// 10 + 0; // 没有遇到字符串,false转换为0
// 10 + undefined; // 没有遇到字符串,做数学运算,undefined转换为NaN
// NaN + []; // 没有遇到字符串,做数学运算,[]属于对象,于是先通过toString([])把[]转为字符串'',+号遇到字符串做拼接处理,隐藏'NaN'
// 'NaN' + 'Tencent'; // 字符串拼接
// 'NaNTencent' + null; // 字符串拼接
// 'NaNTencentnull' + true; // 字符串拼接
// 'NaNTencentnulltrue' + {}; // Object.prototype.toString({}) => [object Object]
// 结果为 'NaNTencentnulltrue[object Object]'

即使一边是字符串,遇到++/+也不一定是字符串拼接,以下三种情况是数学运算。

let l = '10';
console.log(l++); // 10

let n = '10';
console.log(++n); // 11

let m = '10';
console.log(+m); // 10

其他情况

{}+0; // 0 => 这种情况,{}会被认为是代码块,不参与运算,+0结果就是0
({}+0); // '0[object Object]' => 用括号包起来,是一个整体,就参与数学运算了
0+{}; // '0[object Object]'
+{}; // 'NaN' => +只有右侧有,一定是做数学运算
{}+{}; // 'NaN' => 不理解
let arr = [10, 18, 0, 10, 25, 23];
arr = arr.map(parseInt);
console.log(arr);

有些我以为的但结果并不是的点:

null == 0; // false => 除了undefined,null与其他值都不相等
null == false; // false => 除了undefined,null与其他值都不相等
null == ''; // false => 除了undefined,null与其他值都不相等
undefined == 0; // false => 除了null,undefined与其他值都不相等
undefined == false; // false => 除了null,undefined与其他值都不相等
undefined == ''; // false => 除了null,undefined与其他值都不相等
Number([]); // 0
Number({}); // NaN
Number(); // 0
Number(''); // 0
Number(null); // 0
Number(undefined); // NaN

2、其他数据类型转换为字符串

  • 能直接使用的方法
    • toString()
    • String()
  • 隐式转换(一般都是调用其toString)
    • 加号运算的时候,如果某一边出现字符串,再去转换为数字
    • 把对象转换为数字,需要先toString()转换为字符串,再去转换为数字
    • 基于alert/confirm/prompt/document.write等这些方法输出内容,都是要把累充先转换为字符串,然后再输出

把其他类型转换为字符串,一般都是直接用""包起来,只有{}普通对象调取toString是调取Object.prototype.toString,不是转换为字符串,而是检测数据类型,返回结果是"[object Object]"

3、其他数据类型转换为布尔

  • 基于以下方法可以把其他数据类型转换为布尔
    • ! 转换为布尔值后取反
    • !! 转换为布尔类型
    • Boolean([value])
  • 隐式转换
    • 在循环或者条件判断中,条件处理的结果就是布尔类型值

规则:只有0,NaN,null,undefined,空字符串 这五个值会变为布尔值false,其余都是true

4、==运算符比较的转换规律:

  • 类型一样的几个特殊点:
    • {}=={} => false,对象比较的是堆内存的地址
    • []==[] => false
    • NaN==NaN => false
  • 类型不一样的转换规则
    • 对象==字符串 => 对象转化为字符串
    • null==undefined => 值为true。但是换成===结果是false(类型不一致),剩下null/undefined和其他任何数据类型值都不相等
    • 剩下两边只要类型不同都转换为数字再进行比较
console.log([]==false); // true
// 对象==布尔,都转换为数字(隐式转换)
// 对象转数字,先toString转换为字符串(应该是先基于valueOf获得原始值,没有原始值再去toString),再转换为数字的 -> toString([]) => '' => 0
// false转换为数字为0
// 因此 0==0true

console.log(![]==false); // true
// !的优先级比==高,先运行左侧
// 左侧是一个表达式,只有0,空字符串,null,undefined,NaN转换为布尔值false,其他都转换为true,因此![]得到结果是falsefalsefalse比较结果为true

[55]==55; // true
// 对象==数字,两边类型不同,转换为数字再进行比较,其中对象先要转为字符串
// 因为[55].toString()结果是'55',在转成数字为55,因此结果是true

5、Object.is([value1], [value2]);

检测两个值是否相等。

Object.is(NaN, NaN); // true