在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
。
答案 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!
}