JavaScript中将字符串转换为数字的最快方法是什么?

132

任何数字都是数字。看起来像数字的字符串也是数字。其他所有的东西都是NaN(非数字)。

'a' => NaN
'1' => 1
1 => 1

什么最快取决于特定实现在特定时间的优化。没有客观上的“最快”方式。 - I Hate Lazy
2
'1a' 字符串应该怎么处理? ' 1' 呢?换句话说,为什么通常使用的方法( Number(x)parseInt(x, 10) )对您来说并不足够? - raina77ow
之前的jsperf测试:http://jsperf.com/converting-string-to-int/3 - epascarello
这里有一个不错的性能比较,涉及不同的方法:http://jsben.ch/#/NnBKM - EscapeNetscape
10个回答

206

据我所知,有4种方法可以做到这一点。

Number(x);
parseInt(x, 10);
parseFloat(x);
+x;

通过我所做的这个快速测试,实际上取决于浏览器。

https://jsben.ch/NnBKM

Implicit 在三种浏览器中标记为最快,但会使代码难以阅读...因此选择你喜欢的方式吧!


7
有趣的是,Google Analytics(嵌入网站的部分)使用1*进行日期到数字的转换,这与上面的+类似,例如使用1*new Date()而不是+new Date()。可能这样更易读? - Matthew Wilcoxson
1
我认为1*更好,因为它更少出错。在+1之前出现的不需要的悬挂变量并不是解析错误。这类似于在C中使用if (MYCONSTANT == myvar)的技巧。 - Tomas
6
目前的优化似乎更偏向于使用本地方法而不是隐式转换。在Chrome 37.0.2062.124上的Windows Server 2008 R2 / 7中,Number()是最快的,在Firefox 30.0中ParseInt()是最快的,而隐式转换则是两者中最慢的。此外,您可以考虑将字符串浮点数包括在普通比较测试中。我的猜测是在某些情况下它可能会改变顺序,因为字符串转浮点数通常比字符串转整型慢。目前的测试方式是在使用Number()时进行字符串到整型的转换。 - Nolo
2
Chrome 61.0.3163。 Number() 是最快的。 - Dmitry Petukhov
我刚刚在 https://jsben.ch 上比较了 Number()~~,结果 Number() 赢了,尽管有时它们的表现几乎相同。 - Andrew

72

至少有5种方法可以实现这个:

如果您只想转换为整数,另一种快速(且简短)的方法是使用双重位非(即使用两个波浪线字符):

例如:

~~x;

参考:http://james.padolsey.com/cool-stuff/double-bitwise-not/

到目前为止,我所知道的将字符串转换为数字的5种常见方法都有所不同(虽然还有更多位运算符可以使用,但它们都会给出与~~相同的结果)。这个JSFiddle演示了您可以在调试控制台中期望看到的不同结果:http://jsfiddle.net/TrueBlueAussie/j7x0q0e3/22/

var values = ["123",
          undefined,
          "not a number",
          "123.45",
          "1234 error",
          "2147483648",
          "4999999999"
          ];

for (var i = 0; i < values.length; i++){
    var x = values[i];

    console.log(x);
    console.log(" Number(x) = " + Number(x));
    console.log(" parseInt(x, 10) = " + parseInt(x, 10));
    console.log(" parseFloat(x) = " + parseFloat(x));
    console.log(" +x = " + +x);
    console.log(" ~~x = " + ~~x);
}

调试控制台:

123
  Number(x) = 123
  parseInt(x, 10) = 123
  parseFloat(x) = 123
  +x = 123
  ~~x = 123
undefined
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
null
  Number(x) = 0
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = 0
  ~~x = 0
"not a number"
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
123.45
  Number(x) = 123.45
  parseInt(x, 10) = 123
  parseFloat(x) = 123.45
  +x = 123.45
  ~~x = 123
1234 error
  Number(x) = NaN
  parseInt(x, 10) = 1234
  parseFloat(x) = 1234
  +x = NaN
  ~~x = 0
2147483648
  Number(x) = 2147483648
  parseInt(x, 10) = 2147483648
  parseFloat(x) = 2147483648
  +x = 2147483648
  ~~x = -2147483648
4999999999
  Number(x) = 4999999999
  parseInt(x, 10) = 4999999999
  parseFloat(x) = 4999999999
  +x = 4999999999
  ~~x = 705032703

~~x版本在“更多”情况下会返回一个数字,而其他版本通常会返回undefined,但对于无效的输入(例如,如果字符串包含有效数字后面的非数字字符),它将失败并返回0

溢出

请注意:使用~~可能会导致整数溢出和/或位截断,但其他转换不会。虽然输入如此大的值是不寻常的,但您需要意识到这一点。示例已更新以包括更大的值。

一些性能测试表明,标准的parseIntparseFloat函数实际上是最快的选项,可能被浏览器高度优化,但这取决于您的要求,因为所有选项都已足够快:http://jsperf.com/best-of-string-to-number-conversion/37

所有这些都取决于性能测试的配置,因为有些测试显示parseInt/parseFloat要慢得多。

我的理论是:

  • 谎言
  • 该死的行数
  • 统计数据
  • JSPerf结果 :)

5
针对大于2147483647的数字要特别小心,例如~~4294967296将返回0 - Joseph Goh
@JosephGoh:等我有机会的时候,我会扩展结果以包括int范围溢出。通常,如果数字这么大,你会有一个非常特殊的接口,所以需要注意溢出。干杯! - iCollect.it Ltd
@JosephGoh:有趣的是,在Chrome中,您不会得到0,而是得到超过有符号最大值的负数。当您超过无符号整数最大值时,它似乎只是丢弃额外的位。例如:"4999999999" => 705032703 - iCollect.it Ltd

10

使用+运算符在字符串前加上前缀。

console.log(+'a') // NaN
console.log(+'1') // 1
console.log(+1) // 1

8

将字符串转换为整数的快速方法是使用按位或,如下所示:

x | 0

虽然这取决于实现方式,但从理论上讲,它应该相对快速(至少与+x一样快),因为它首先会将x转换为数字,然后执行非常高效的或运算。


是的,但我认为这种技术会截断大整数,这很糟糕。值得注意的是,可以使用“Math.floor()”的替代方法,但问题相同。 - Jean
这里是一个与第一个答案的方法相结合的各种位运算符的jsperf。我随机排序,因为我发现有些浏览器会基于先前测试中类似代码来优化下一个测试。与顶部回答者不同,我发现隐式方法是最糟糕的方法。 - Pluto

4

以下是简单的方法:var num = Number(str); 在这个例子中,str 是包含字符串的变量。 您可以测试并查看它的工作方式:打开Google Chrome 开发者工具,然后进入控制台并粘贴以下代码。 阅读注释以更好地理解转换过程。

// Here Im creating my variable as a string
var str = "258";


// here im printing the string variable: str
console.log ( str );


// here Im using typeof , this tells me that the variable str is the type: string
console.log ("The variable str is type: " + typeof str);


// here is where the conversion happens
// Number will take the string in the parentesis and transform it to a variable num as type: number
var num = Number(str);
console.log ("The variable num is type: " + typeof num);

4
我发现num * 1非常简单清晰,适用于整数和浮点数...

3

这可能不是特别快的方法,但它具有确保数字至少达到某个值(例如0)或最多达到某个值的附加好处:

Math.max(input, 0);

如果你需要确保一个最小值,通常做法如下所示
var number = Number(input);
if (number < 0) number = 0;

Math.max(..., 0) 可以让你只用一句话实现原本需要两句话才能完成的操作。


为什么不使用Math.abs(input)呢?它还可以将字符串转换为正数,并节省一些额外的字符。 - Aaron Gillion
1
@AaronGillion:Math.max(-5,0)将返回0;Math.abs(-5)将返回5。这取决于使用情况,哪个更有意义。 - Dan Dascalescu
1
哦,糟糕,是的,在我写下那个评论的深夜,我的用例完全不同。 - Aaron Gillion
如果“input”无法转换为数字,则会得到“NaN”。 - Domas Mar

1

将字符串转换为数字的七种方法:

let str = "43.2"

1. Number(str) => 43.2 2. parseInt(str) => 43 3. parseFloat(str) => 43.2 4. +str => 43 5. str * 1 => 43.2 6. Math.floor(str) => 43 7. ~~str => 43

这是按性能排序的吗?OP要求“最快的方法”。 - Kalnode

0
你可以尝试使用我们刚刚正式发布的测量和数据类型转换库UnitOf!UnitOf非常快速、体积小,能够高效地转换任何数据类型,而且永远不会抛出错误或null/undefined。当转换失败时,将返回您定义的默认值或UnitOf的默认值。
//One liner examples
UnitOf.DataType("12.5").toFloat(); //12.5 of type Float is returned. 0 would be returned if conversion failed.
UnitOf.DataType("Not A Num").toInt(10); //10 of type Int is returned as the conversion failed.

//Or as a variable
var unit = UnitOf.DataType("12.5");
unit.toInt(5); //12.5 of type Float is returned. 5 would be returned if the conversion failed.
unit.toFloat(8); // 12 of type Int is returned. 8 would be returned if the conversion failed.

-1

最快的方法是使用-0:

const num = "12.34" - 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接