如何实现一个parseInt

更新日期: 2020-03-22阅读: 2.1k标签: 类型
function(string, [radix]) {}

如果string不为字符串类型, 则先将string转化为字符串类型

string会忽略前后的空白

依次解析字符, 如果字符不是指定基数中的字符( 例如:2进制中的3、 10进制中的'f' )则停止解析( 首字符为'+'或'-'时除外 ), 返回已经解析好的整数

如果无法解析为整数, 则返回NaN

radix 默认值不为10, 在radix为undefined、0或者没有指定时, 做以下处理

  • 如果string以'0X'或'0x'开头时, 基数为16
  • 如果string以'0'开头时, 基数为8或者10(每个浏览器的具体实现不同, es5规定此时为10)
  • 如果string以其他任何字符开头时, 基数为10

radix的范围为2-36


不考虑进制radix

代码实现

const _parseInt = (str, radix) => {
  if (typeof str !== 'string') str = String(str)
  str = str.trim()
  const regex = /^(?<fuhao>[\+|\-]*)(?<num>\d+)/
  if (!regex.test(str)) return NaN
  const groups = str.match(regex).groups
  radix = 10
  const arr = groups.num.split('')
  const len = arr.length
  let result = 0
  for(let i = 0; i < len; i++) {
    const num = arr[i] * Math.pow(10, len - i - 1)
    if (isNaN(num)) break
    else result += num
  }
  return result * (groups.fuhao === '-' ? -1 : 1)
}

测试用例

const assert = require('assert')
assert.strictEqual(_parseInt(null), NaN)
assert.strictEqual(_parseInt('0e0'), 0)
assert.strictEqual(_parseInt('08'), 8)
assert.strictEqual(_parseInt(0.0000003), 3)
assert.strictEqual(_parseInt(0.00003), 0)
assert.strictEqual(_parseInt(-0.0000003), -3)
assert.strictEqual(_parseInt('6.022e23'), 6)
assert.strictEqual(_parseInt(6.022e2), 602)


考虑radix

代码实现

const _parseInt = (str, radix) => {
  // 不为string类型先转化为string 类型
  if (typeof str !== 'string') str = String(str)

  // 删除首尾空白
  str = str.trim()

  // 正则匹配[+|-]?[0]?[Xx]?[0-9a-fA-F]+
  const regex = /^(?<fuhao>[\+|\-]*)(?<radix>[0]?[Xx]?)(?<num>[0-9a-fA-F]+)/

  // 无法匹配返回NaN
  if (!regex.test(str)) return NaN

  // 匹配出符号、进制、数字三个分组
  const groups = str.match(regex).groups

  // radix的有效范围为 2-36
  if (radix && (radix < 2 || radix > 36)) return NaN

  // 如果没有指定radix, radix 会有以下默认值
  if (!radix) {
    if (groups.radix.toUpperCase() === '0X') radix = 16
    else if (groups.radix === '0') radix = 8
    else radix = 10
  }

  // 挨个字符串解析,如果遇到无法解析时则停止解析,返回已经解析好的整数
  let splitArr = groups.num.split('')
  const arr = []
  for(let i = 0; i < splitArr.length; i++) {
    // 根据charCode来做转行为实际数据, 0-9为[48-57],A-F为[65-70]
    const charCode = splitArr[i].toUpperCase().charCodeAt()
    let num 

    // 字符为[A-F]时, 实际数字为charCode -55
    if(charCode >= 65) num = charCode - 55

    // 字符为[0-9]时, 实际数字为charCode - 48
    else num = charCode - 48

    // 当实际数字大于radix时, 无法解析则停止字符串遍历
    if (num > radix) {
      break
    } else {
      arr.push(num)
    }
  }

  const len = arr.length
  // 当实际数字数组长度为0时, 返回NaN
  if(!len) return NaN
  let result = 0

  // 依次解析实际数字数组, 组合成真正的数字
  for(let i = 0; i < len; i++) {
    const num = arr[i] * Math.pow(radix, len - i - 1)
    result += num
  }

  // 算法匹配到的正负号
  return result * (groups.fuhao === '-' ? -1 : 1)
}

测试用例

const assert = require('assert')

// 以下返回15
assert.strictEqual(_parseInt('0xF', 16), 15)
assert.strictEqual(_parseInt('F', 16), 15)
assert.strictEqual(_parseInt('17', 8), 15)
assert.strictEqual(_parseInt(021, 8), 15)
assert.strictEqual(_parseInt('015', 10), 15)
assert.strictEqual(_parseInt(15.99, 10), 15)
assert.strictEqual(_parseInt('15,123', 10), 15)
assert.strictEqual(_parseInt('FXX123', 16), 15)
assert.strictEqual(_parseInt('1111', 2), 15)
assert.strictEqual(_parseInt('15 * 3', 10), 15)
assert.strictEqual(_parseInt('15e2', 10), 15)
assert.strictEqual(_parseInt('15px', 10), 15)
assert.strictEqual(_parseInt('12', 13), 15)

// 以下返回NaN
assert.strictEqual(_parseInt('Hello', 8), NaN)
assert.strictEqual(_parseInt('546', 2), NaN)  

// 以下返回-15
assert.strictEqual(_parseInt('-F', 16), -15)
assert.strictEqual(_parseInt('-0F', 16), -15)
assert.strictEqual(_parseInt('-0XF', 16), -15)
assert.strictEqual(_parseInt(-15.1, 10), -15)
assert.strictEqual(_parseInt(' -17', 8), -15)
assert.strictEqual(_parseInt(' -15', 10), -15)
assert.strictEqual(_parseInt('-1111', 2), -15)
assert.strictEqual(_parseInt('-15e1', 10), -15)
assert.strictEqual(_parseInt('-12', 13), -15)

// 以下返回4
assert.strictEqual(_parseInt(4.7, 10), 4)
assert.strictEqual(_parseInt(4.7 * 1e22, 10), 4)
assert.strictEqual(_parseInt(0.00000000000434, 10), 4)

// 以下返回224
assert.strictEqual(_parseInt('0e0', 16), 224)
原文:https://www.cnblogs.com/xnlc/p/12558643.html


链接: https://fly63.com/article/detial/8364

JS中Null与Undefined的区别

在JavaScript中存在这样两种原始类型:Null与Undefined。这两种类型常常会使JavaScript的开发人员产生疑惑,在什么时候是Null,什么时候又是Undefined?Undefined类型只有一个值,即undefined。当声明的变量还未被初始化时,变量的默认值为undefined。

Javascript的类型检测

主要介绍了JS中检测数据类型的几种方式,typeof运算符用于判断对象的类型,但是对于一些创建的对象,它们都会返回\'object\',有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到instanceof运算符

js类型转换的各种玩法

对于object和number、string、boolean之间的转换关系,ToPrimitive是指转换为js内部的原始值,如果是非原始值则转为原始值,调用valueOf()和toString()来实现。

JavaScript类型:关于类型,有哪些你不知道的细节?

Undefined类型表示未定义,它的类型只有一个值为undefined。undefined和null有一定的表意差别。非整数的Number类型无法使用 == 或 === 来比较,因为 JS 是弱类型语言,所以类型转换发生非常频繁

为你的 JavaScript 项目添加智能提示和类型检查

近在做项目代码重构,其中有一个要求是为代码添加智能提示和类型检查。智能提示,英文为 IntelliSense,能为开发者提供代码智能补全、悬浮提示、跳转定义等功能,帮助其正确并且快速完成编码。

js的类型

基本类型:按值访问,可以操作保存在变量中实际的值;引用类型数据存在堆内存,而引用存在栈区,也就是说引用类型同时保存在栈区和堆区,关于==的执行机制,ECMASript有规范,因为==前后的值交换顺序,返回的值也是一样的,所以在此对规范做出如下总结

再也不用担心 JavaScript 的数据类型转换了

JavaScript 是一种弱类型或者说动态类型语言。所以你不用提前声明变量的类型,在程序运行时,类型会被自动确定,你也可以使用同一个变量保存不同类型的数据。

JavaScript基础之值传递和引用传递

js的值传递和引用(地址)传递:js的5种基本数据类型 number,string,null,undefined,boolean 在赋值传递时是值传递,js的引用数据类型(object,array,function)进行引用传递,其实底层都是对象。

JS中的布尔 数字 字符串

JS中所有的值都可以转换成布尔类型 使用Boolean()或者 !!(两个感叹号),JS中所有的值都可以转换成数字类型,使用Number()或+。数字类型转换场景目的只有一个,用于计算,将后台传递的数据,从字符串转换为数字并参与计算

if条件中,js的强制类型转换

众所周知,JS在很多情况下会进行强制类型转换,其中,最常见两种是:1.使用非严格相等进行比较,对==左边的值进行类型转换2.在if判断时,括号内的值进行类型转换,转化为布尔值

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!