Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js —— 全局对象:函数属性(parseFloat/parseInt) #102

Open
lizhongzhen11 opened this issue Apr 25, 2020 · 0 comments
Open
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Apr 25, 2020

全局对象:函数属性(parseFloat/parseInt)

parseFloat ( string )

  • MDN
  • parseFloat 函数产生一个 Number 值,该值由将字符串参数的内容解释为十进制数来决定。
  • parseFloat 函数就是 %parseFloat% 固有对象。
  • 先把参数转为 String 类型,然后判断是否满足 StrDecimalLiteral 的语法!
  • 注意这里要满足的是 StrDecimalLiteral,不是 StringNumericLiteral!!!
  • 单一的空字符串不满足 StrDecimalLiteral 语法,所以 parseFloat('') 结果为 NaN
// 示例来源于MDN,加了点补充
parseFloat(3.14); // 3.14
parseFloat('3.14'); // 3.14
parseFloat(9n); // 9
parseFloat('314e-2'); // 3.14
parseFloat('0.0314E+2'); // 3.14
parseFloat('3.14some non-digit characters'); // 3.14
parseFloat('3.14.2.6'); // 3.14
parseFloat('0.0314E+2.5-9'); // 3.14
parseFloat(''); // NaN
parseFloat(undefined); // NaN
parseFloat(null); // NaN
parseFloat(true); // NaN
parseFloat(false); // NaN
parseFloat([]); // NaN
parseFloat({}); // NaN
parseFloat({ toString: function() { return "3.14" } }); // 3.14

// 太大失去精度时的表现
Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MAX_SAFE_INTEGER + 4 // 9007199254740996
parseFloat('9007199254740995') // 9007199254740996
  1. 定义 inputString? ToString(string)
  2. 定义 trimmedString! TrimString(inputString, start)
  3. 如果 trimmedStringtrimmedString 的任何前缀都不满足 StrDecimalLiteral 的语法,返回 NaN
  4. 定义 numberStringtrimmedString 的最长前缀,可能是 trimmedString 自己,满足 StrDecimalLiteral 的语法
  5. 定义 mathFloatnumberStringMV (数学值)
  6. 如果 mathFloat = 0R
    1. 如果 trimmedString 的第一个码元是 0x002D(减号),返回 -0
    2. 返回 +0
  7. 返回 mathFloatNumber 类型值

注意:parseFloat 只能将字符串的开头部分解释为 Number 值;它会忽略无法解释为十进制文字符号的任何码元,并且不会给出任何此类码元被忽略的指示。

parseInt ( string, radix )

  • MDN
  • parseInt 函数产生一个 整数 值,该整数值由对 string 参数内容根据指定的进制基数 radix 的解释来决定。字符串中的前导空格会被忽略。
  • 如果 radixundefined0,除非以 0x0X 开始(这种情况 radix 被认为是 16),否则 radix 被推断为 10
  • 如果 radix16,可能会以 0x0X 开始。
  • parseInt 函数就是 %parseInt% 固有对象。
// 来源于MDN + 补充
parseInt(0); // 0
parseInt(-0, 10); // 0
parseInt(0.9); // 0
parseInt(Infinity, 10); // NaN
0.99999999999999999 // 1
parseInt(0.99999999999999999); // 1
Number.MAX_SAFE_INTEGER // 9007199254740991
parseInt(Number.MAX_SAFE_INTEGER + 4, 10); // 9007199254740996
parseInt(9007199254740995n, 10); // 9007199254740996
parseInt(1n, 10); // 1

parseInt(); // NaN
parseInt(null); // NaN
parseInt(null, 10); // NaN
parseInt(undefined, 10); // NaN
parseInt(true); // NaN
parseInt(false); // NaN

parseInt([], 10); // NaN
parseInt({}, 10); // NaN
parseInt({toString() {return 1}}, 10); // 1

parseInt('', 10); // NaN
parseInt('7+6', 10) // 7
parseInt("15e2", 10); // 15

parseInt("015", 10); // 15
parseInt(015, 10); // 13
parseInt("0xF", 16); // 15
parseInt("F", 16); // 15
parseInt("1111", 2); // 15

parseInt(4.7 * 1e22, 10); // 4
parseInt(0.00000000000434, 10); // 4
  1. 定义 inputString? ToString(string)
  2. 定义 S! TrimString(inputString, start)
  3. 定义 sign 为 1
  4. 如果 S 不为空且 S 的第一个码元是 0x002D(减号),设置 sign 为 -1
  5. 如果 S 不为空且 S 的第一个码元是 0x002B(加号)或 0x002D(减号),从 S 中移除第一个码元
  6. 定义 R? ToInt32(radix)
  7. 定义 stripPrefixtrue
  8. 如果 R ≠ 0
    1. 如果 R < 2R > 36,返回 NaN
    2. 如果 R ≠ 16,设置 stripPrefixfalse
  9. 否则,
    1. 设置 R 为 10
  10. 如果 stripPrefixtrue
    1. 如果 S 的长度至少是 2 且 S 的前两个码元是 0x0X
      1. S 中移除前两个码元
      2. 设置 R 为 16
  11. 如果 S 包含的不是 R 进制的码元,定义 ZS 的子串,该子串由第一个此类码元 之前 的所有码元组成(例如 parseInt('7+6', 10)+6 会被忽略);否则,定义 ZS
  12. 如果 Z 为空,返回 NaN
  13. 定义 mathInt 为由 ZR 进制表示的 数学整数 值,将字母 A-Za-z 用于表示数值从10到35的数字。(但是,如果 R 是 10 且 Z 包含超过 20 个有效数,第20个数后面的每个有效数可能会被0替换,由具体实现决定;如果 R 不是 2,4,8,10,16,32mathInt 可能是由 ZR 进制表示依赖于具体实现的近似的 数学整数 值)
  14. 如果 mathInt = 0R
    1. 如果 sign = -1,返回 -0
    2. 返回 +0
  15. 定义 numbermathIntNumber 类型值
  16. 返回 sign × number

注意:parseInt 只能将字符串的开头部分解释为整数值;它会忽略不能被解释为整数值的部分。

经典面试题

[1, 2, 3].map(parseInt) 输出什么以及为什么?

[1, 2, 3].map(parseInt) // [1, NaN, NaN]

首先 parseInt 是函数,map 中接受的参数也是函数,所以上述代码可以转为:

[1, 2, 3].map((item, index) => {
  return parseInt(item, index)
})

这样一看,实际是对以下代码的求值:

parseInt(1, 0) // 1
parseInt(2, 1) // NaN
parseInt(3, 2) // NaN

根据上面 parseInt 算法规定,第二个参数 radix 如果等于 0,那么会采用十进制;如果不等于 0,则要看它是不是在 2 ~ 36 范围内。所以:

  • parseInt(1, 0) 实际上是 parseInt(1, 10)
  • parseInt(2, 1),1 不在 2 ~ 36 范围内,返回 NaN
  • parseInt(3, 2),2 在 2 ~ 36 范围内,所以这里是二进制形式,但是二进制中只有 01,没有 3,这里 3 不符合二进制规范,所以返回 NaN

本篇结束

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant