我应该静态分配Javascriptstring的内存性能?

所以我正在写这个node.js应用程序,我试图让它超快速,并且占用内存很less。 我有很多string连接,function如下:

function f(pt) { return pt.x + ' + ' + pt.y; } 

如果我在应用程序的内部循环中执行了1亿次这样的操作,JavaScript引擎是否需要分配并且必须释放string' + ' 1亿次? 将这些代码重写成类似的东西,会不会是更高效的记忆方式?

 var plus = ' + '; function f(pt) { return pt.x + plus + pt.y; } 

还是编译器只是在后台执行这个操作,还是不要紧? (我的代码实际上使用的string比“+”长得多,我只是用它作为例子)。

这取决于。

但说实话,这可能会慢一些。
这是因为它必须在函数范围内searchvariablesplus ,然后在窗口对象上面find它。

所以,我相信可能会慢一些。

考虑下面的代码:

 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%!

在下面,您可以看到大致相同的时间:

铬控制台

你也可以在电脑上testing它!

 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')); }; 
 <font face="sans-serif"> <p> Plus inside: <span id="plus_inside"></span><br> &nbsp;&nbsp;fn: <code>function(pt){return pt.x + ' + ' + pt.y}</code> </p> <p> Plus outside: <span id="plus_outside"></span><br> &nbsp;&nbsp;fn: <code>function(pt){return pt.x + plus + pt.y}</code> </p> <p> Array: <span id="array"></span><br> &nbsp;&nbsp;fn: <code>function(pt){return [pt.x,'+',pt.y].join(' ')}</code> </p> <p> Array (no join): <span id="array_nojoin"></span><br> &nbsp;&nbsp;fn: <code>function(pt){return [pt.x,' + ',pt.y].join('')}</code> </p> <p> Array (replace comas): <span id="array_replace"></span><br> &nbsp;&nbsp;fn: <code>function(pt){return ([pt.x,'+',pt.y]+'').replace(',',' ')}</code> </p> </font> 

string串联可以通过将string推入数组来加速。 然后join数组。

 ["a","b","c"].join(''); 

这是因为join是一个调用,编译器也可以立即计算结果string的全长。

这将取决于实现,但至less就V8(Chrome)而言,不,每个函数调用都不会实例化一个新的' + ' 。 最有可能的是,函数体被编译成一次连接的操作。

您可以通过首先定义一个函数(在控制台中)来看到这一点:

 var f = function(a, b) { return a + ' + ' + b; }; 

然后启动堆分析器并执行此操作:

 var c = f('1', '2'); 

分析器显示的是在此期间只分配一个string:

 "1 + 2" 

这似乎意味着它甚至不把这两个单独的连接操作视为单独的操作。 这一切都是一回事。

底线:这样的微观优化不可能让你走得更远。 正如Ismael指出的那样,这实际上可能会减慢你的代码速度。