【问题标题】:Javascript Concatenate Array to StringJavascript将数组连接到字符串
【发布时间】:2013-10-03 03:57:00
【问题描述】:

我正在使用 D3.js,并且经常发现自己在动态构建 transform 属性(或 path 元素上的 d 属性)。这两者通常都需要多个逗号分隔的数字。

有时我通过将数组连接到字符串来构建我的字符串:

var x = 0,
y = 1,
path = 'M0,0 L' + [x, y];

有时我会通过手动添加逗号来构建字符串:

var x = 0,
y = 1,
path = 'M0,0 L' + x + ',' + y;

我决定我应该尝试坚持一种方法或另一种方法,但我想知道哪种方法更好。

我考虑过以下几点:

  • 我知道调用join() 比手动连接逗号要慢,但是浏览器在将数组连接到字符串时会这样做吗?
  • 第二种格式适用于任何浏览器。有没有不支持第一种格式的浏览器?
  • 第一种格式使用较少的字符(保持文件较小总是一个优点)。
  • 就个人而言,我认为第一种格式更具可读性。

有没有一种方法绝对比另一种更好?还是我只是挑剔?

【问题讨论】:

  • 你只是在吹毛求疵 :-) 我会选择更具可读性的一个(在我看来,这是第二个)。

标签: javascript arrays string d3.js


【解决方案1】:

简短的回答:使用 array.join。

长答案:

首先,连接并不比使用 array.join() 快,它更慢。这是因为每次连接时都会销毁两个字符串并创建一个新字符串。

获取以下代码:

<script>
function concat(){
var txt = '';
for (var i = 0; i < 1000000; i++){
txt =+ i + ',';
}
}

function arr(ar){
var txt = 'asdf' + ar;
}

ar = [];
for (var i = 0; i < 1000000; i++) {
ar.push(i);
}

concat();

arr(ar);

alert('done!');
</script>

并将其粘贴到 html 文件中。然后对其进行剖析。在我的机器(核心 i7EE、16GB RAM、SSD 磁盘、IE9)上,arr() 需要 0 毫秒,而 concat() 需要 12 毫秒。请记住,这是超过一百万次迭代(同样的测试在 IE6 上会有很大的不同,concat() 需要几秒钟)。

其次,当只有两个值时,连接将与 array.join 相同。因此,对于您的示例,从性能的角度来看,它们都是等效的。如果您使用上面的代码并将 1000000 更改为 4,则 concat 和 arr 都需要 0ms 才能执行。这意味着您的特定流程的差异要么不存在,要么可以忽略不计,它不会显示在配置文件中。

第三,现代浏览器无论如何都使用 array.join() 优化字符串连接,所以从性能的角度来看,讨论可能没有实际意义。

这给我们留下了风格。就个人而言,我不会使用第一种形式,因为我不喜欢手动连接字符串(当你有 2 个变量时,它相当简单,但是如果你有 10 个变量呢?那会产生很长的代码行。如果你收到一个包含 n 个值的数组,会出现一个 for 循环)。我也不会使用第二种形式,因为正如另一个答案中指出的那样,该值被强制转换为字符串,这意味着正在进行一些隐式转换。这里的问题是隐含的部分。我知道现在数组在强制时用逗号连接,但是如果规范发生变化,或者某些天才决定在您的代码库中更改 Array.prototype 的 toString 实现会发生什么?只是为了好玩在 jsfiddle 中运行它:

Array.prototype.toString = function() {
return 'not the expected result!';
}

alert([1, 2]);

你能猜出答案是什么吗? (上面的代码将执行与您的代码相同的数组转换。通过 toString() 方法强制)

如果你使用 array.join(',');您将通过说明 1) 无论 toString 实现如何,都将连接您的数组,以及 2) 它将用逗号连接,从而对您的代码进行未来验证。

【讨论】:

  • 我同意你关于隐式转换的观点——这是我没有想到的。但是,我不同意您的性能测试。我在一行代码中构建我的字符串,而不是在循环中迭代。一个更好的测试用例是这样的(见这个小提琴jsfiddle.net/8VqEP)。您会在此处看到 TenorB 答案中的性能评级是准确的。
  • 测试的目的是表明任何差异都可以忽略不计(12 毫秒几乎没有),并说明在处理大字符串时字符串连接有多慢(1000000 次迭代会产生长字符串) .您的小提琴将加入数组与连接一个非常小的字符串进行了比较。在稍微修改之后(您在每次迭代中构建数组,这可能会污染测试,因为我们正在分析连接,而不是对象创建),我回到我的第二点。我的时间是 502、2 和 91,对于最慢的测试,每次迭代大约是 0.000502 毫秒。可以忽略不计。
  • 这让我们回到了我的帖子的意图。由于性能可以忽略不计,出于上述原因,您应该使用 array.join
  • 似乎 jsfiddle 为分析增加了一些开销。如果您本机运行代码(即从加载到浏览器中的 html 文件),结果为 266、238、180;使 array.join() 最快(这些只是我的结果,它们在您的环境中可能会有所不同,但它们证明了我的观点:性能可以忽略不计)。
【解决方案2】:

当 JavaScript 将数组强制转换为字符串时,它实际上在数组上调用:.join(',')。因此,您实际上将手动使用.join(',') 获得更好的性能,而不是让解释器注意到您正在强制数组。所以:x + ',' + y 是最快的,[x, y].join(',') 是最佳实践(因为它更容易修改行为),[x, y] 比手动调用 .join 慢一点,有时可能无法读取,但更方便。

【讨论】:

  • 我很惊讶地发现x + ',' + y 实际上快了多少。就我而言,它比[x, y] 快了大约 4 倍。 (jsfiddle.net/8VqEP)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2022-01-22
  • 2017-02-14
  • 2017-01-19
  • 1970-01-01
  • 2015-05-20
相关资源
最近更新 更多