【问题标题】:What converts to number in JavaScript? [closed]什么在 JavaScript 中转换为数字? [关闭]
【发布时间】:2014-02-01 14:46:54
【问题描述】:

JavaScript 中(奇怪的)数字转换背后的秘密是什么?

我已经设法在下面介绍的几个测试用例中找出了一些使用isnumeric 函数的方法。

//
function isnumeric(n) {
  try {
    return (isFinite(n = n.valueOf()) || ((1 / 0 === Math.abs(n)) && (n + n === n)))
      && eval(n) === parseFloat(Number(n));
  } catch (b) {}
  return false;
}

console.clear();
[
.1, 1, 0, "0", Infinity, 1/0, -1/0, +null, 01, 037, 1 + [], 
Math.pow([], 2), 0xff, 0x12ef, +[], -[], -1/[], []/Infinity, 
"0x12", 1/null, null/1, Math.sqrt([]), []/1, Infinity/[], new Date, 
Math.E, "1.2e-12", 0.1e11, null + +[], Math.sqrt(null), 1/"\t\r\n ",
" \t\r\n\uFEFF\xA0\x0B\u2028\u2029\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"/1
].every(isnumeric);
//
// true
// 

isFinite(n = n.valueOf()) 处理 numeric-like-values(字符串、数字、日期),

(1 / 0 === Math.abs(n)) && (n + n === n) 从(字符串)"Infinity" 中过滤掉 Infinity

eval(n) === parseFloat(Number(n)) 部分句柄 string-numerics 包含字符:“x、e”等。

谢谢!

【问题讨论】:

  • 你有什么问题?
  • EEK。 evaling 随机字符串是个坏主意。
  • >>> JavaScript 中(奇怪的)数字转换背后的秘密是什么?
  • 你能详细说明这意味着什么吗?哪些数字转换?在什么情况下?
  • ...'评估随机字符串是个坏主意';它不会评估随机字符串,它们不会在 eval 发生之前通过测试。

标签: javascript numbers type-conversion


【解决方案1】:

由于我真的不知道你在问什么,所以我会回答所有问题。

n.valueOf

(spec, mdn)

这个调用是在一个数字object(而不是一个数字primitive)被传递给函数的情况下完成的:

var numObj = new Number(4),
    numPrim = 4;

console.log(typeof numObj, typeof numPrim); //object, number
numObj === numPrim; //false
//however:
numObj.valueOf() === numPrim; //true

isFinite

(spec, mdn)

isFinite(arg)arg 转换为一个数字(稍后我会谈到),并检查它是否不是 NaN、+∞ 或 -∞ 之一:

isFinite(4); //true
isFinite(Infinity); //false
isFinite("Infinity"); //false (the argument is converted into a number)
isFinite("foobar"); //false (converting a random string to a number yields NaN

(1 / 0 === Math.abs(n))

1/0 给我们带来了 +∞,所以这会检查参数是 +∞ 还是 -∞。 InfinityisFinite 调用捕获(注意这有多么奇怪:isFinite 被用作修剪因子......但我们仍然希望 Infinity 是一个数字)。

(n + n === n)

再次,这捕获了Infinity,因为它是满足这个等式的唯一值(没有检查,但它是有道理的;我会在最后讨论它)。很没用,真的。

eval(n) === parseFloat(Number(n))

(parseFloat: spec, mdn) (编号:specmdn)。

这是一只奇怪的兔子。它背后的原因超出了我的理解。左边执行n 好像是js,右边将n 转换为数字。两次。这希望实现的是可能捕获NaN 或无效的数字字符串。

它属于冗余部门有几个原因:

  1. Number 调用内部的ToNumber 函数,该函数将参数转换为基于js语法的数字。因此,如果参数是无效数字,则返回值将是NaNeval 最后会做同样的事情,但开销更大。

  2. parseFloat 的外部调用是荒谬的。 parseFloat 将其参数转换为字符串,然后尝试查看字符串是否以有效数字开头。这已经在Number 中完成了,这也比parseFloat 更严格(因为前者要求整个字符串都是有效数字,而不仅仅是开头)。

  3. ToNumber 已在 isFinite 中调用。如果参数是NaN 或不是数字的字符串,我们会得到false

所以这个函数包含不必要的重复和一些不合逻辑的调用。取自this great answer,可以写成:

function isNumeric (n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

开启ToNumber

当您执行4 * [] 时,会发生什么(section 11.5)是取运算符的每一边,转换为一个数字,然后计算答案。它们如何转换为数字?那是section 9.3, the ToNumber function。在大多数情况下,您会看到奇怪的行为,这是因为您使用对象作为要操作的值之一,并且该对象被转换为字符串(有关示例,请参见 this question)。

【讨论】:

    猜你喜欢
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2022-08-16
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    相关资源
    最近更新 更多