所以我正在编写这个node.js应用程序,我正试图让它超级快,内存占用少。我有很多字符串连接,函数如下:
function f(pt) {
return pt.x + ' + ' + pt.y;
}
如果我在我的应用程序的内循环上这样做了1亿次,Javascript引擎是否分配并且必须释放该字符串' + '
1亿次?将此代码重写为
var plus = ' + ';
function f(pt) {
return pt.x + plus + pt.y;
}
或者编译器是否只是在后台执行此操作,或者甚至不重要? (我的代码实际上使用了比'+'更长的字符串,我只是用它作为例子。)
答案 0 :(得分:5)
取决于。
但说实话,它可能会慢一点
这是因为它必须在函数范围内搜索变量plus
,然后在窗口对象上搜索,然后在上面的范围内查找它。
所以,我相信它可能会变慢。
请考虑以下代码:
console.time('plus outside');
var plus=' x ', fn=function(pt){return pt.x + plus + pt.y};
for(var i=0; i<1e5; i++){ fn({x:5,y:6}); }
console.timeEnd('plus outside');
这段代码:
console.time('plus inside');
var fn=function(pt){return pt.x + ' + ' + pt.y};
for(var i=0; i<1e5; i++){ fn({x:5,y:6}); }
console.timeEnd('plus inside');
在谷歌浏览器v41.0.2272.89米上运行,plus outside
耗时200毫秒,内部耗时 175 毫秒!
这快了25%!
下面,您可以看到大致相同的版画屏幕:
您也可以在计算机上测试它!
window.onload=function(){
(function(elem){
var plus=' + ',fn=function(pt){return pt.x + plus + pt.y}, start=new Date();
for(var i=0; i<1.5e7; i++){ fn({x:5,y:6}); };
var end=new Date();
elem.innerHTML=(end-start)+'ms (i:'+i+')';
})(document.getElementById('plus_outside'));
(function(elem){
var fn=function(pt){return pt.x + ' + ' + pt.y}, start=new Date();
for(var i=0; i<1.5e7; i++){ fn({x:5,y:6}); };
var end=new Date();
elem.innerHTML=(end-start)+'ms (i:'+i+')';
})(document.getElementById('plus_inside'));
(function(elem){
var fn=function(pt){return [pt.x,'+',pt.y].join(' ')}, start=new Date();
for(var i=0; i<2e5; i++){ fn({x:5,y:6}); };
var end=new Date();
elem.innerHTML=(end-start)+'ms (i:'+i+')';
})(document.getElementById('array'));
(function(elem){
var fn=function(pt){return [pt.x,' + ',pt.y].join('')}, start=new Date();
for(var i=0; i<2e5; i++){ fn({x:5,y:6}); };
var end=new Date();
elem.innerHTML=(end-start)+'ms (i:'+i+')';
})(document.getElementById('array_nojoin'));
(function(elem){
var fn=function(pt){return ([pt.x,'+',pt.y]+'').replace(',',' ')}, start=new Date();
for(var i=0; i<2e5; i++){ fn({x:5,y:6}); };
var end=new Date();
elem.innerHTML=(end-start)+'ms (i:'+i+')';
})(document.getElementById('array_replace'));
};
&#13;
<font face="sans-serif">
<p>
Plus inside: <span id="plus_inside"></span><br>
fn: <code>function(pt){return pt.x + ' + ' + pt.y}</code>
</p>
<p>
Plus outside: <span id="plus_outside"></span><br>
fn: <code>function(pt){return pt.x + plus + pt.y}</code>
</p>
<p>
Array: <span id="array"></span><br>
fn: <code>function(pt){return [pt.x,'+',pt.y].join(' ')}</code>
</p>
<p>
Array (no join): <span id="array_nojoin"></span><br>
fn: <code>function(pt){return [pt.x,' + ',pt.y].join('')}</code>
</p>
<p>
Array (replace comas): <span id="array_replace"></span><br>
fn: <code>function(pt){return ([pt.x,'+',pt.y]+'').replace(',',' ')}</code>
</p>
</font>
&#13;
答案 1 :(得分:2)
可以通过将字符串推送到数组来加速字符串连接。然后加入阵列。
["a","b","c"].join('');
这是因为join是一次调用,编译器也可以立即计算结果字符串的全长。
答案 2 :(得分:1)
这将取决于实现,但至少就V8(Chrome)而言,不,每个函数调用似乎都不会实例化新的' + '
。很可能函数体被编译成一次性连接的操作。
您可以通过首先定义一个函数(在控制台中)来看到这一点:
var f = function(a, b) { return a + ' + ' + b; };
然后启动堆分析器并执行:
var c = f('1', '2');
探查器显示的是在此期间只分配了一个字符串:
"1 + 2"
这似乎意味着它甚至不将两个单独的连接操作视为单独的操作。它一次性完成所有这一切。
底线:像这样的微优化不太可能让你走得太远。正如Ismael指出的那样,它实际上可能会降低您的代码速度。