13

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

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

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

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

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

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

以下是我考虑过的几件事:

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

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

4

2 回答 2

17

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

于 2013-09-27T01:38:05.223 回答
5

简短的回答:使用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 个 var 时,它相当简单,但如果你有 10 个 var 怎么办?那会产生很长的代码行。如果你收到一个包含 n 个值的数组,会出现一个 for 循环)。我也不会使用第二种形式,因为正如在另一个答案中指出的那样,该值被强制转换为字符串,这意味着正在进行一些隐式转换。这里的问题是隐含的部分。我知道现在数组在强制时用逗号连接,但是如果规范发生变化,或者某些天才决定在您的代码库中更改 Array.prototype 的 toString 实现会发生什么?只是为了好玩在 jsfiddle 中运行它:

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

alert([1, 2]);

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

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

于 2013-09-27T02:04:16.497 回答