什么转换为JavaScript中的数字?

时间:2014-02-01 14:46:55

标签: javascript numbers type-conversion

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())处理类似数字的值(字符串,数字,日期),

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

eval(n) === parseFloat(Number(n))部分处理 string-numerics 持有字符:“x,e”等。

谢谢!

1 个答案:

答案 0 :(得分:4)

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

n.valueOf

specmdn

如果将数字对象(而不是数字原语)传递给函数,则完成此调用:

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

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

isFinite

specmdn

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给我们带来+∞,所以这会检查参数是+∞还是-∞。 Infinity电话中发现了isFinite(请注意这是多么奇怪:isFinite被用作修剪因素......但我们仍然希望Infinity成为一个数字)

(n + n === n)

同样,这会抓住Infinity,因为它是满足这个等式的唯一值(没有检查,但它有意义;我最后会谈到它)。真的很无用。

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

(parseFloat:specmdn) (编号:specmdn)。

这是一个奇怪的兔子。背后的原因超出了我的想法。左侧执行n,就像它是js一样,右手将n转换为数字。两次。希望实现的目标可能是捕获NaN或无效的数字字符串。

它属于冗余部门,原因如下:

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

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

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

  4. 所以这个函数包含不需要的重复和一些不合逻辑的调用。取自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)。