【JS基础回归】关于parseInt 与 numberObj.toString 中的“raidx”

本文深入解析了JavaScript中parseInt与toString方法中的radix参数的用途与注意事项,包括其在不同进制转换中的应用,以及在特定场景下如canvas像素数据处理中的角色。

一、关于radix的疑问

parseInt以及toString是经常用到的两个方法,如下所示

parseInt (string [, radix])

numberObj.toString ( [ radix ] )

我们通常会这样使用:

parseInt('123abc');  //输出 123

var num = 123;
num.toString();  //输出 '123'

那么,radix这个参数的作用是?神马场景下会用到?有什么注意事项?下文会简单讲解

二、关于parseInt与toString里的radix

parseInt (string [, radix])

作用

讲解可见:http://www.w3school.com.cn/js/jsref_parseInt.asp

常见使用场景

  1. 将字符串转成对应整数
  2. 将2进制数据转成对应的10进制数据,如canvas API里对像素数据的处理时可以用到(比如将读取的10进制像素数据各种处理,比如低位替换,然后再转回10进制)

注意点:

w3school里的解释其实挺详细了,归纳起来要点如下:

  1. radix可选,取值范围为2-36(包含2与36)
  2. 如指定了radix,且radix为合法值,则用radix来解析string;如radix非法,返回NaN
  3. 如无指定radix,且string不以'0x'或者'0X'开头,则radix默认为10;
  4. 如无指定radix,且string以'0x'或者'0X'开头,则radix默认为16;

简单看如下demo,大致可以不同情况下radix对于最终结果的影响。至于对于string的解析,不再这里进行讨论,可参考上面那个链接

parseInt(11);  //输出 11

parseInt(11, 2);  //输出 3
parseInt(11, 36);  //输出 37
parseInt(11, 38);  //输出 NaN

parseInt('0x11');  //输出 17
parseInt('0x11', 10);  //输出 0

 

numberObj.toString ( [ radix ] )

作用

  将数字numberObj转成其对应radix进制的字符串

常见使用场景

  1. 将10进制数据转成对应的2进制数据。比如canvas里对像素点的低二位数据进行处理,需现将像素点的RGB值转成对应的二进制数据(默认读取到的是10进制的)

参见:

  http://www.w3school.com.cn/js/jsref_tostring_number.asp

注意点

  1. radix可选,默认为10,合法值为2-36(包含2与36)
  2. 当radix不是2-36的整数时,会抛出RangeError错误,而不是想parseInt那样简单返回NaN之类的
  3. “当调用toString方法的对象不是Number时,抛出typeError错误”,这句话略费解。其实这里指的是Number.prototype.toString,即Number对象的原型方法,这个看下demo可能更直观点

demo如下,Number.prototype.toString.call('123')这种调用方式是相当奇怪的,至今没有这种需求的场景,所以知道有这么回事就可以了

var num = 123;

num.toString();  //输出 '123'
num.toString(2);  //输出 '1111011'

num.toString(37);  //输出 'RangeError: toString() radix argument must be between 2 and 36'

'123'.toString(2);  //输出 '123'
Number.prototype.toString.call('123');  //输出 'TypeError: Number.prototype.toString is not generic'

三、关于radix取值范围的限制

看了下EC 5里面对radix的限制,没有说明这个取值范围的原因,于是问了下hax大神,hax大神简单明了地回答

36 = 10数字 + 26字母。

于是仿佛明白了什么。。。0 1 2 3 4 5 ... A B C ... Y Z

有种被鄙视的感觉,羞惭满面。。。

 

四、写在后面

文中示例如有错漏,请指出;如觉得文章对您有用,可点击“推荐” :)

转载于:https://www.cnblogs.com/chyingp/archive/2012/12/17/parseInt_toString_radix.html

<think> 我们分析给定的JavaScript函数`hexadecimal`: ```javascript const hexadecimal = (num: string, x: number, y?: number): string => { if (y !== undefined) { return parseInt(num.toString(), y).toString(x) } else { return parseInt(num.toString()).toString(x) } } ``` ### 步骤分析 1. **函数功能**:该函数用于将数字字符串`num`从`y`进制(如果提供)转换为十进制,然后再转换为`x`进制。如果未提供`y`,则默认将`num`视为十进制字符串,再转换为`x`进制。 2. **参数说明**: - `num`:输入的数字字符串(类型标注为`string`,但实际调用可能传入其他类型?) - `x`:目标进制(基数) - `y`(可选):源进制(基数) 3. **潜在问题**: - **参数类型问题**:函数期望`num`是字符串,但调用时可能传入非字符串(如数字)。代码中使用了`num.toString()`,这可以处理非字符串的情况(如数字、布尔值等),但需要注意`null`和`undefined`。 - 当`num`为`null`时,`num.toString()`会抛出错误(`TypeError: Cannot read property 'toString' of null`)。 - 当`num`为`undefined`时,同样会抛出错误(`TypeError: Cannot read property 'toString' of undefined`)。 - **进制范围**:`parseInt`的第二个参数(进制)必须在2到36之间(包括2和36),否则返回`NaN`。同样,`toString`的参数也必须在2到36之间(包括2和36),否则会抛出`RangeError`。 - **特殊值处理**: - 如果`num`是空字符串,`parseInt('', y)`会返回`NaN`(当`y`存在时)或`parseInt('')`返回`NaN`(当`y`不存在时)。然后调用`NaN.toString(x)`会返回字符串`"NaN"`,这可能不是期望的结果。 - 如果字符串包含非指定进制的字符,`parseInt`会尽可能转换直到遇到非法字符(例如`parseInt("123abc", 10)`返回`123`)。但需要注意,如果第一个字符就无法转换,则返回`NaN`。 - **数值范围**:`parseInt`只能处理整数,且转换大数时可能丢失精度(因为JavaScript的数字是双精度浮点数,能精确表示的整数范围是`-2^53+1`到`2^53-1`)。超出这个范围的整数,转换将不准确。 - **负数处理**:`parseInt`可以处理负数字符串(例如`parseInt("-10", 10)`返回`-10`),但是转换后的负数再转换为其他进制时,`toString`方法不会直接处理负数(例如`(-10).toString(2)`返回`"-1010"`)。这可能是可接受的,但要注意负数的进制转换规则。 4. **改进建议**: - 增加参数校验:检查`x`和`y`(如果提供)是否在2到36之间。 - 处理`null`和`undefined`:可以先将`num`转换为字符串,如果为`null`或`undefined`,则按需处理(例如返回空字符串或抛出错误)。 - 处理空字符串和`NaN`:当转换结果为`NaN`时,可能需要返回错误提示或特定值。 ### 总结 该函数在输入合法且进制参数在有效范围内时,可以正常工作。但存在以下问题: 1. 对`null`和`undefined`输入会抛出异常。 2. 对空字符串输入会返回`"NaN"`。 3. 未对进制参数做范围检查,可能导致`parseInt`返回`NaN`(进制无效时)或`toString`方法抛出异常(进制无效时)。 4. 可能丢失精度(当数字超出安全整数范围时)。 ### 改进代码 ```javascript const hexadecimal = (num, x, y) => { // 处理num为null或undefined的情况 if (num === null || num === undefined) { throw new Error('Input cannot be null or undefined'); } // 将num转为字符串 const numStr = num.toString(); // 检查进制参数 const radixList = [x, y].filter(r => r !== undefined); for (const r of radixList) { if (r < 2 || r > 36) { throw new RangeError(`Radix must be between 2 and 36, inclusive. Received: ${r}`); } } let decimal; if (y !== undefined) { decimal = parseInt(numStr, y); } else { decimal = parseInt(numStr); } // 检查parseInt结果是否为NaN if (isNaN(decimal)) { return 'NaN'; // 或者根据需求返回其他值,或抛出错误 } return decimal.toString(x); }; ``` ### 注意事项 - 改进版增加了对`null`和`undefined`的检查,避免调用`toString`时出错。 - 检查进制参数是否在2到36之间。 - 处理`parseInt`结果为`NaN`的情况(例如输入字符串包含无效字符)。 ### 相关问题 1. JavaScript中`parseInt`函数处理不同进制字符串的规则是什么? 2. 如何安全地处理JavaScript中的数值进制转换? 3. 在JavaScript中,如何避免大数进制转换时的精度丢失问题? </think> ### 分析 JavaScript 函数 `hexadecimal` #### 函数功能说明 ```javascript const hexadecimal = (num: string, x: number, y?: number): string => { if (y !== undefined) { return parseInt(num.toString(), y).toString(x); } else { return parseInt(num.toString()).toString(x); } } ``` 该函数实现进制转换功能: 1. 当提供三个参数时:将字符串 `num` 从 `y` 进制 → 十进制 → `x` 进制 2. 当提供两个参数时:将字符串 `num` 从十进制 → `x` 进制 --- ### 存在问题分析 #### 1. **类型处理缺陷** - **问题**:参数 `num` 声明为 `string`,但调用 `num.toString()` 会导致: - 传入非字符串时触发隐式转换(如 `true.toString()` → `"true"`) - 传入 `null`/`undefined` 时抛出 `TypeError` - **示例**: ```javascript hexadecimal(null, 16); // 抛出 TypeError hexadecimal({}, 16); // 返回 "[object Object]" 的进制转换结果 ``` #### 2. **进制范围未校验** - **问题**:未检查 `x` 和 `y` 的取值是否在 `2-36` 的有效范围 - **风险**: ```javascript hexadecimal("10", 1); // 抛出 RangeError (toString参数需≥2) hexadecimal("10", 37); // 抛出 RangeError (最大支持36进制) ``` #### 3. **特殊值处理缺失** - **问题**:未处理 `parseInt()` 返回 `NaN` 的情况 - **示例**: ```javascript hexadecimal("abc", 16); // 返回 "NaN" (期望处理错误或返回空) hexadecimal("12.3", 16); // 返回 "12" (忽略小数部分) ``` #### 4. **负值处理异常** - **问题**:负数的进制转换结果不符合预期 - **示例**: ```javascript hexadecimal("-10", 16, 10); // 返回 "-a" (期望统一处理符号) ``` --- ### 修复建议 #### 改进版本代码 ```javascript const safeHexadecimal = ( num: string | number, targetRadix: number, sourceRadix?: number ): string => { // 1. 类型安全处理 if (num === null || num === undefined) { throw new Error("Input cannot be null/undefined"); } const numStr = String(num); // 2. 进制范围校验 (2-36) const radixList = [targetRadix, sourceRadix].filter(Boolean); if (radixList.some(r => r < 2 || r > 36)) { throw new RangeError("Radix must be between 2 and 36"); } // 3. 转换核心逻辑 const decimalValue = parseInt( numStr, sourceRadix ?? 10 // 默认十进制 ); // 4. 处理无效值 if (isNaN(decimalValue)) { return ""; // 或根据需求抛错 } // 5. 处理负值 (统一保留符号) const sign = decimalValue < 0 ? "-" : ""; return sign + Math.abs(decimalValue).toString(targetRadix); }; ``` #### 改进点说明 | 问题类型 | 修复方案 | 示例验证 | |-----------------|-----------------------------------|------------------------------| | 类型安全 | 显式转换为 `String()` | `safeHexadecimal(null, 16)` → 抛错 | | 进制范围校验 | 检查 `2 ≤ radix ≤ 36` | `safeHexadecimal("10", 1)` → 抛错 | | 特殊值处理 | 返回空字符串或自定义错误 | `safeHexadecimal("abc", 16)` → `""` | | 负值处理 | 拆分符号和绝对值处理 | `safeHexadecimal("-10", 16, 10)` → `"-a"` | --- ### 关键注意事项 1. **进制转换规范** JavaScript 的 `parseInt` 和 `toString` 遵循以下规则: - `parseInt("0x10", 16)` → 16(自动识别十六进制前缀) - `(255).toString(16)` → `"ff"`(小写输出) 2. **边界场景验证** ```javascript // 有效案例 safeHexadecimal("1010", 2, 10); // "1111110010" (10进制10 → 2进制) safeHexadecimal("ff", 10, 16); // "255" (16进制ff → 10进制) // 无效案例 safeHexadecimal("12.3", 16); // "12" (parseInt截断小数) safeHexadecimal("", 16); // "" (空字符串返回空) ``` --- ### 相关问题 1. JavaScript 中 `parseInt` 函数处理不同进制字符串的规则是什么[^1][^5]? 2. 如何正确处理 JavaScript 数值转换中的 `NaN` 和边界值[^3][^4]? 3. 在进制转换时,如何确保大整数的精度不丢失(如超过 `Number.MAX_SAFE_INTEGER` 的情况)? 4. JavaScript 的隐式类型转换在数值运算中会产生哪些意外行为[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值