Number 数字相关的方法, 强制 、隐式类型转换 、进制之间转换

Number

  注意:浮点数的运算,在计算机中是不够精确的
  2e3  // 2 * 10³ => 2000
  10E-2  // 10 * 10⁻² => 0.1

相关方法:

  1. parseFloat(str) 把字符串转成 小数 或 整数

    • str 是字符串,如果不是字符串,浏览器会启动隐式转换默认将其转换为字符串,然后再进行 parseFloat 转换。如果是字符串,浏览器会从字符串左侧第一个字符开始查找,把找到的有效数字字符最后转为数字(如果一个都没找到,结构是NaN),直到遇到非有效数字字符则立即停止查找,不论后面是否还有有效数字字符,都不会继续往后面查找了。parseFloat 可以识别小数点。
  2. parseInt(str, radix) 把字符串转成 整数

    • 参数是 字符串(规则同 parseFloat,不可识别小数点)
    • radix 基数,告诉函数需要按哪种进制进行输出,默认十进制,范围是 2~36,如果不在这个范围内的,结果就是NaN
  3. toFixed(num) 保留 num 位小数
    参数是 数字 代表要保留的小数位数,会4舍5入

  4. toLocaleString() 方法可把一个 Number 对象转换为本地格式的字符串。
    返回值:数字的字符串表示,由实现决定,根据本地规范进行格式化,可能影响到小数点或千分位分隔符采用的标点符号。
    问题:1. 浏览器兼容问题,2. 由于国际化标准的不同,不同环境输出的结果可能不一样。

const a = 1234567891000;
const b = 673439.4542;

console.log(a.toLocaleString()); // "1,234,567,891,000"
console.log(b.toLocaleString()); // "673,439.454"  (小数部分四舍五入了)
  1. Number(str) 字符串转数字
    该方法会触发隐式类型转换,下文会详细提及。

数字与字符串相互转换

Number("123")  // 123
123.toString()  // "123"

实例应用:

强制类型转换

/*这两种方法转 空字符串,或者以字母开头(比如str="px12334") 输出结果都是 NaN */
let str = "100.456px";
    console.log(parseFloat(str));//"100.456"
    console.log(parseInt(str));//"100"
    console.log(parseFloat(str).toFixed(2));//"100.46"

隐式类型转换

  1. Number() 方法会进行隐式类型转换,并最终输出数值类型为止。
    规则:
// 字符串转数字:只要遇到非有效数字字符,结果就为NaN
Number("") // 0
Number("123") // 123
Number("123x") // NaN

// 其它基础数据类型转换结果
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN

// 会去除末尾的 n ,如果超过最大安全数字,就会采用科学计算法来进行显示
Number(10n) // 10
Number(100000000000000000000000000000000n) // 1e+32

/*
把对象转换为数字:
  + 先调用对象的 Symbol.toPrimitive 这个方法,如果不存在这个方法(结果是undefined),目前已知的只有`new Date()`有这个方法
  + 再调用对象的 valueOf 获取原始值,如果获取的不是原始值,
  + 再调用对象的 toString 把其变成字符串
  + 最后再把字符串基于 Number 转换为数字
*/ 
Number([]) // 0
Number([2]) // 2
Number([2, 3]) // NaN
Number({}) // NaN

对象内部的 Symbol.toPrimitive 的机制

xxx[Symbol.toPrimitive](hint){
  // hint:'number' / 'string' / 'default'
  // + number: 获取当前对象的数字类型的原始值
  // + string:获取当前对象的字符串类型的原始值
  // + default:根据操作获取数字或者字符串类型的原始值

重写对象内部的 Symbol.toPrimitive

  let obj = {
    name: 'liangyu',
    age: 12,
    [Symbol.toPrimitive](hint) {
      let result;
      switch (hint) {
        case 'number':
          result = 0;
          break;
        case 'string':
          result = JSON.stringify(obj);
          break;
        default:
          result = "";
      }
      return result;
    }
  };
  console.log(Number(obj)); // hint: 'number'  => 0
  console.log(String(obj)); // hint: 'string'  => {"name":"liangyu","age":12}
  console.log(10 + obj); // hint: 'default'  => "10"
  console.log(10 - obj); // hint: 'number'  => 10

  1. 不同类型的值进行 比较、运算 时也会产生隐式类型转换。详细的隐式类型转换

进制转换

parseInt(11, 2).toString(10) // 将二进制的11转成十进制,=> 3
parseInt(11, 10).toString(2) // 将十进制的11转成二进制,=> 1011
// 错误的二进制数,会输出NaN、1等不正确结果,需要控制输入的内容正确
// 同理可以将 任何进制的数转成任何进制

面试题

第一题:

  let ary = [27.2, 0, '0013', '14px', 123];
  ary = ary.map(parseInt)
  console.log(ary);

解答:
先看看 map 做了什么

  ary.map(function(item, index) { // 数组中有多少项,回调函数就被执行多少次
    // item:当前迭代的项
    // index:对应的索引
    return "xxx"; // 原始数组不变,返回一个新数组,return 后面的值就是 新数组的每一项。
  });

解题过程:
map每一次循环,回调函数都会执行一次parseInt(item, index)
回调函数第一次执行:parseInt(27.2, 0),parseInt 先将第一个参数 27.2 转成 "27.2",第二个参数 为非有效范围,进行布尔值转换,为 false,走默认的十进制。最后相当于执行了parseInt("27.2", 10) => 27
第二次执行:parseInt(0, 1),1不是有效的进制范围,=> NaN
第三次执行:parseInt('0013', 2),找到符合二进制的内容"001",把二进制的"001"转换为十进制0*2^2 + 0*2^1 + 1*2^0 => 1
第四次执行:parseInt('14px', 3),找到符合三进制的内容"1",把三进制的"1"转换为十进制1*3^0 => 1
第五次执行:parseInt(123, 4),把数字123转成"123",找到符合四进制的内容"123",把四进制的"123"转换为十进制1*4^2 + 2*4^1 + 3*4^0 => 27
所以最后console.log(ary); => [27, NaN, 1, 1, 27]

posted @ 2018-11-11 20:22  真的想不出来  阅读(675)  评论(0编辑  收藏  举报