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

761

在速度优势、清晰度优势、内存优势等方面,将数字转换为字符串的“最佳”方法是什么?

以下是一些示例:

  1. String(n)

  2. n.toString()

  3. ""+n

  4. n+""


这个问题对我来说似乎足够清晰明了。 - qwr
25个回答

738
像这样:
var foo = 45;
var bar = '' + foo;

实际上,尽管我通常出于简便考虑而这样做,在超过1,000次迭代时,似乎对于原始速度来说 .toString() 有优势

在此处查看性能测试(不是我编写的,但当我准备编写自己的测试时找到了这个):http://jsben.ch/#/ghQYR

基于上述JSPerf测试,最快的方法是:str = num.toString();

应该注意的是,考虑到它可以以任何方式进行转换100万次,耗时0.1秒,速度差异并不太明显。

更新:速度似乎因浏览器而异。在Chrome中,num + ''似乎是最快的,根据此测试:http://jsben.ch/#/ghQYR

更新2:再次基于我的上面的测试,应该注意Firefox 20.0.1执行.toString()大约比'' + num示例慢100倍。


79
有些情况下转换可能无法返回预期的答案:'' + 123e-50 返回 "1.23e-48"。翻译为:转换时可能会出现意外结果,例如 '' + 123e-50 的转换结果为 "1.23e-48" - hongymagic
38
@hongymagic:实际上,那个答案是唯一可以想到的:数字不关心也不知道它是如何输入的,标准的打印表示法是小数点前正好有一个数字。 - Svante
5
我在 http://jsben.ch/ghQYR 上运行了测试,每次结果都不同! - Maryam Saeidi
3
我喜欢这个答案,因为 null foo 不会抛出错误。 - ttugates
2
@MaryamSaeidi:使用drublic的_jsperf.com_测试似乎更加一致。 - Giraldi
显示剩余8条评论

503

在我看来,n.toString()以其清晰易懂的特点获得了胜利,我认为它没有任何额外的开销。


32
这不安全。n 可能为 null 或未定义。 - david.pfx
96
@david.pfx,这个问题是关于如何将数字值转换为字符串的。提供一些不是数字的例子(例如nullundefined),并不会使这个答案变得“不安全”。 - Michael Martin-Smucker
12
如果你写了很多 JavaScript,你会意识到事情很少这么简单明了。这个问题是开放性的,我认为一个好的回答至少应该承认字符串实际上可能是 null 或 undefined 的问题。个人经验因人而异。 - david.pfx
15
@david.pfx,什么样的确定性?我的观点是nullundefined没有答案,不抛出错误并不是处理它,隐藏它也会导致“代码失败”。我不喜欢你轻蔑的说法,比如“也许是时候写更少的代码,多看一些”,我建议你不要在论点中使用人身攻击,并且这次我愿意忽略它。 - George Reith
13
@david.pfx 如果你使用 '' + undefined,会得到 'undefined' 这个结果,但在我看来这并没有什么改善,甚至更糟,因为它会默默失败。同样的情况也适用于 ('' + null) === 'null' - Maciej Krawczyk
显示剩余4条评论

115

对于新手来说,显式转换更为清晰明了。使用类型强制转换如其他人所建议的那样,如果开发者不知道强制转换规则,则会导致歧义。最终,开发者时间比 CPU 时间更有价值,因此我会以后者为代价优化前者。话虽如此,在这种情况下,差异可能微不足道,但如果确实存在,我相信有一些不错的 JavaScript 压缩器将会优化这种情况。

因此,出于以上原因,我会选择:n.toString()String(n)String(n) 可能是更好的选择,因为如果 n 为 null 或 undefined,则不会失败。


22
问题是关于转换数字,而不是关于转换数字、nullundefined。如果由于程序中的错误原因导致 nnullundefined,那么我更希望程序在这种状态下失败,以便更好地发现和修复错误。程序崩溃是程序员的福音,可以帮助她找到错误 :-)。另一种选择是交付不按设计工作的软件,并仔细掩盖错误。因此,我不喜欢使用 String(n) 掩盖错误。 - Matt Wallis
2
String(n) 在函数式编程中非常实用,例如在 Underscore 的结合函数 _.compose(funcThatNeedsAStringParam, String) 中使用。 - Rik Martins
7
使用String(null)不会导致程序崩溃,但它会返回字符串"null",这可能不是你想要的。如果数据可能为空,那么你需要显式地处理它。 - Peter Smartt
2
@MattWallis 我认为这应该是开发者的决定,而不是回答者,你觉得呢? - forresthopkinsa

54
下面是在JS中将Integer转换为String的方法,按性能从高到低排列。
var num = 1

方法 1:

num = `${num}`

方法二:

num = num + ''

方法3:

num = String(num)

方法四:

num = num.toString()

注意: 不能直接在数字上调用toString()方法。 2.toString() 会抛出Uncaught SyntaxError: Invalid or unexpected token

(性能测试结果由@DarckBlezzer在他的回答中给出)


4
你可以使用2..toString()。注意那两个点号。 - Ron Martinez
@RonMartinez 有趣的行为 - Arun Joseph

49

其他答案已经涵盖了其他选项,但我更喜欢这个:

s = `${n}`

简短、简洁,已经在许多其他地方使用(如果您正在使用现代框架/ ES版本),因此任何程序员都能理解它。

虽然这通常并不重要,但与其他方法相比,它似乎也是速度最快的之一。


1
如果 n 未定义,则使用 .toString() 将会抛出语法错误。 - Jee Mok
2
这不是在所有情况下都会产生与 String(n) 相同的结果吗?唯一的区别是它不够清晰。 - Bennett McElwee
2
而且慢得多。 - Adrian Bartholomew
1
如果 nundefined\${n}`返回字符串'undefined'。更好的方法是 `${n || ''}`,如果 nundefinednull,则返回空字符串。**注意**:如果 n = 0,它也会返回 ''。更复杂(但速度较慢),可以返回 '0' 而不是空字符串:`${!isNaN(n) ? n : n || '' }``。 - phse
1
@AdrianBartholomew - 只是出于兴趣,你为什么说它慢得多?根据这些结果,显然它更快,或者说是最快的 - 请查看测试4的结果。 - Greenonline
显示剩余2条评论

41
...JavaScript的解析器会尝试将数字上的点符号解析为浮点数字面量。
2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first

来源


21

明显是半开玩笑的:

var harshNum = 108;
"".split.call(harshNum,"").join("");

或者在ES6中,您可以简单地使用模板字符串

var harshNum = 108;
`${harshNum}`;

如果我使用ES6模板运行基准测试,有时甚至比'' + number方法更快。尽管如此,在多次执行这些基准测试时,结果会有很大的变化,因此不确定是否应该过于认真对待它们。 - Nico Van Belle

13
我使用https://jsperf.app创建了以下测试案例:
number + ''
`${number}`
String(number)
number.toString()

https://jsperf.app/yineye

截至2018年7月24日的结果显示,在Chrome浏览器中,number + '' 是最快的,在Firefox浏览器中,它与模板字符串字面量并列。 String(number)number.toString()这两种方法比最快的选项慢大约95%。

performance tests, description above


12

将任何变量转换为字符串的最简单方法是将一个空字符串添加到该变量。

5.41 + ''    // Result: the string '5.41'
Math.PI + '' // Result: the string '3.141592653589793'

2
请注意,需要将其放在括号内:(5.41 + ''),以使用String方法,如.substring()和其他方法。 - Gjaa
1
为什么需要注意这个? - Adrian Bartholomew

11

我推荐使用`${expression}`,因为你不需要担心错误。

[undefined,null,NaN,true,false,"2","",3].forEach(elem=>{
  console.log(`${elem}`, typeof(`${elem}`))
})

/* output
undefined string
null      string
NaN       string
true      string
false     string
2         string
          string
3         string
*/


以下可以测试速度,但是顺序会影响结果。(在StackOverflow上) 你可以在你的平台上测试它。

const testCases = [
  ["${n}", (n) => `${n}`], // 
  ['----', undefined],

  [`"" + n`, (n) => "" + n],
  [`'' + n`, (n) => '' + n],
  [`\`\` + n`, (n) => `` + n],
  [`n + ''`, (n) => n + ''],
  ['----', undefined],

  [`String(n)`, (n) =>  String(n)],
  ["${n}", (n) => `${n}`], // 

  ['----', undefined],
  [`(n).toString()`, (n) => (n).toString()],
  [`n.toString()`, (n) => n.toString()],

]

for (const [name, testFunc] of testCases) {
  if (testFunc === undefined) {
    console.log(name)
    continue
  }
  console.time(name)
  for (const n of [...Array(1000000).keys()]) {
    testFunc(n)
  }
  console.timeEnd(name)
}


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