为什么在javascript中使用辅助函数构建字符串?

时间:2014-04-22 16:57:34

标签: javascript string

https://developers.google.com/speed/articles/optimizing-javascript

上看到了这个

有人可以解释一下这是如何更有效的,即为什么这会避免临时字符串结果?

  

通过传递字符串构建器(数组或数组)构建长字符串   helper class)进入函数,避免临时结果字符串。

     

例如,假设buildMenuItemHtml_需要建立一个字符串   从文字和变量,并将在内部使用字符串生成器,   而不是使用:

var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
  strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();
     

使用:

var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
  this.buildMenuItem_(menuItems[i], strBuilder);
}
var menuHtml = strBuilder.join();

我假设在第一种情况下buildMenuItemHtml_返回string,而在第二种情况下buildMenuItemHtml_string推送到strBuilder

3 个答案:

答案 0 :(得分:2)

重要的细节是它说buildMenuItemHtml_从一堆不同的元素构建一个字符串。在这两个例子之间,这有两种不同的方式:

示例1(直接构建字符串):

function buildMenuItemHtml_(data) {
  return ["<li>",data.x,"</li>"].join();
}

或示例2(使用提供的字符串构建器):

function buildMenuItemHtml_(data, strBuilder) {
  strBuilder.push("<li>");
  strBuilder.push(data.x);
  strBuilder.push("</li>");
}

字符串构建相对昂贵且浪费,因为它需要大量的分配和副本,其中一些是临时的,可能会被抛弃。推入阵列相对便宜,join()即使是大阵列ONCE也比join()多个小阵列好多次。

因此,不是让循环的每次迭代构建一个临时字符串(昂贵),而只是用这些字符串构建另一个字符串(昂贵),指南建议将主字符串构建器直接传递到buildMenuItemHtml_功能。通过这样做,你不需要做任何昂贵的字符串构建,直到你的整个元素集合准备就绪 - 即一次。

答案 1 :(得分:1)

通过将整个函数this.buildMenutItemHtml_推入strBuilder,您实际上是为每个迭代为整个this.buildMenuItemHtml函数及其所有内部变量分配内存,这将创建临时字符串在将字符串值返回strBuilder之前的变量。第二种方法将从内存中的原始this.buildMenutItemHtml返回字符串,并将其推送到strBuilder,使其更有效,因为它不会在每次迭代时分配新内存来处理this.buildMenuItemHtml函数。 / p>

答案 2 :(得分:0)

  

我假设在第一种情况下buildMenuItemHtml_返回了一个字符串

  

在第二种情况下,buildMenuItemHtml_将一个字符串推送到strBuilder。

没有。相关的信息是&#34; 假设buildMenuItemHtml_需要从文字变量 s 建立一个字符串并使用字符串内部建设者&#34;。

现在只需将所有项目直接推送到传递的字符串构建器,而不是使用内部字符串构建器,对其进行评估并将[临时,中间]结果字符串推送到传递的字符串构建器。

如果buildMenuItemHtml_只返回一个文字左右,而不是自己进行任何字符串连接,那就无济于事了。


如果没有buildMenuItemHtml_的实际示例代码,这当然很难理解。也许这会有所帮助:

为:

function buildMenuHtml(menuItems) {
    var strBuilder = ["<ul>"];
    for (var i = 0, length = menuItems.length; i < length; i++) {
        strBuilder.push(buildMenuItemHtml(menuItems[i]));
    }
    strBuilder.push("</ul>");
    var menuHtml = strBuilder.join();
    return menuHtml;
}
function buildMenuItemHtml(item) {
    var innerStrBuilder = ["<li>"];
    for (prop in item)
        innerStrBuilder.push(prop, ": ", item[prop]);
    innerStrBuilder.push("</li>");
    var itemHtml = innerStrBuilder.join();
    return itemHtml;
}

好:

function buildMenuHtml(menuItems) {
    var strBuilder = ["<ul>"];
    for (var i = 0, length = menuItems.length; i < length; i++) {
        buildMenuItemHtml(menuItems[i], strBuilder);
    }
    strBuilder.push("</ul>");
    var menuHtml = strBuilder.join();
    return menuHtml;
}
function buildMenuItemHtml(item, strBuilder) {
    strBuilder.push("<li>");
    for (prop in item)
        strBuilder.push(prop, ": ", item[prop]);
    strBuilder.push("</li>");
    // no intermediate itemHtml!
}