高效的Javascript字符串替换

时间:2008-12-18 14:16:27

标签: javascript string performance replace

嘿那里,我有一块HTML,我将重复使用(在用户访问期间的不同时间,而不是一次)。我认为实现这一目标的最佳方法是创建一个HTML div,隐藏它,并在需要时使用其innerHTML并对几个关键字执行replace()。以HTML块为例......

<div id='sample'>
  <h4>%TITLE%</h4>
  <p>Text text %KEYWORD% text</p>
  <p>%CONTENT%</p>
  <img src="images/%ID%/1.jpg" />
</div>

用动态数据替换这些关键字的最佳方法是......

template = document.getElementById('sample');
template = template.replace(/%TITLE%/, some_var_with_title);
template = template.replace(/%KEYWORD%/, some_var_with_keyword);
template = template.replace(/%CONTENT%/, some_var_with_content);
template = template.replace(/%ID%/, some_var_with_id);

感觉就像我选择了一种愚蠢的方式来做到这一点。有没有人对如何以任何方式更快,更智能或更好地做到这一点有任何建议?在用户访问期间,此代码将经常执行,有时常常每3-4秒执行一次。

提前致谢。

11 个答案:

答案 0 :(得分:80)

看起来你想要使用模板。

//Updated 28 October 2011: Now allows 0, NaN, false, null and undefined in output. 
function template( templateid, data ){
    return document.getElementById( templateid ).innerHTML
      .replace(
        /%(\w*)%/g, // or /{(\w*)}/g for "{this} instead of %this%"
        function( m, key ){
          return data.hasOwnProperty( key ) ? data[ key ] : "";
        }
      );
}

代码说明:

  • 期望templateid成为现有元素的ID。
  • 期待data成为包含数据的对象。
  • 使用两个参数替换来进行替换:
  • 第一个是正则表达式,用于搜索所有%keys%(如果您使用备用版本,则为{keys})。键可以是A-Z,a-z,0-9和下划线_的组合。
  • 第二个是每个匹配都会调用的匿名函数。
  • 匿名函数在数据对象中搜索regexp找到的键。 如果在数据中找到密钥,则返回密钥的值,该值将替换最终输出中的密钥。如果未找到密钥,则返回空字符串。

模板示例:

<div id="mytemplate">
  <p>%test%</p>
  <p>%word%</p>
</div>

电话示例:

document.getElementById("my").innerHTML=template("mytemplate",{test:"MYTEST",word:"MYWORD"});

答案 1 :(得分:18)

您可以调整此代码以执行您想要的操作:

var user = {
    "firstName": "John",
    "login": "john_doe",
    "password": "test",
};

var textbody = ""
+"Hey {firstName},\n"
+"\n"
+"You recently requested your password.\n"
+"login: {login}\n"
+"password: {password}\n"
+"\n"
+"If you did not request your password, please disregard this message.\n"
+"";

textbody = textbody.replace(/{[^{}]+}/g, function(key){
    return user[key.replace(/[{}]+/g, "")] || "";
});

您可能还想查看JavaScriptTemplates

答案 2 :(得分:12)

我怀疑会有更高效的东西。替代方案是将其拆分为多个部分,然后连接,但我认为这不会有效。考虑到每个连接都会产生一个与其操作数大小相同的新字符串,可能更少。

已添加:这可能是最优雅的写作方式。此外 - 你还担心什么?内存使用情况?它很丰富,Javascript有一个像样的内存管理器。执行速度?然后你必须有一些巨大的字符串。恕我直言,这很好。

答案 3 :(得分:7)

Template Replacement

快速简便的解决方案是使用String.prototype.replace方法。
它需要第二个参数,可以是值或函数:

function replaceMe(template, data) {
    const pattern = /\{(.*?)\}/g; // {property}
    return template.replace(pattern, (match, token) => data[token]);
}

实施例

const html = `
    <div>
        <h4>{title}</h4>
        <p>My name is {name}</p>
        <img src="{url}" />
    </div>
`;

const data = {
    title: 'My Profile',
    name: 'John Smith',
    url: 'http://images/john.jpeg'
};

并称之为:

replaceMe(html, data);

答案 4 :(得分:1)

您可以通过链接替换而不是进行所有这些临时分配来提高效率。

即。

with(document.getElementById('sample'))
{
  innerHTML = innerHTML.replace(a, A).replace(b, B).replace(c, C); //etc
}

答案 5 :(得分:1)

如果您愿意使用Prototype library,那么它们具有很好的内置模板功能。

这看起来像是:

element.innerHTML = (new Template(element.innerHTML)).evaluate({
    title: 'a title',
    keyword: 'some keyword',
    content: 'A bunch of content',
    id: 'id here'
})

如果您在循环中运行代码,由于易于创建JSON对象/ Javascript对象文字,这将特别好。

不过,我不希望任何速度增加。

此外,您需要将分隔符样式更改为#{keyword}而不是%keyword%

答案 6 :(得分:1)

你的方法是实现穷人模板系统的标准方法,所以没关系。

查看一些JavaScript模板库(例如JST)可能值得您花些时间。

答案 7 :(得分:1)

此方法生成可以缓存的函数模板:

function compileMessage (message) {

  return new Function('obj', 'with(obj){ return \'' +
    message.replace(/\n/g, '\\n').split(/{{([^{}]+)}}/g).map(function (expression, i) {
      return i%2 ? ( '\'+(' + expression.trim() + ')+\'' ) : expression;
    }).join('') + 
  '\'; }');

}

var renderMessage = compileMessage('Hi {{ recipient.first_name }},\n\n' +

'Lorem ipsum dolor sit amet...\n\n' +

'Best Regarts,\n\n' +

'{{ sender.first_name }}');


renderMessage({
  recipient: {
    first_name: 'John'
  },
  sender: {
    first_name: 'William'
  }
});

返回:

"Hi John,

Lorem ipsum dolor sit amet...

Best Regarts,

William"

答案 8 :(得分:0)

Mustachejs非常适合真正优雅的模板:

<div id='sample'>
  <h4>{{TITLE}}</h4>
  <p>Text text {{KEYWORD}} text</p>
  <p>{{CONTENT}}</p>
  <img src="images/{{ID}}/1.jpg" />
</div>

然后你可以使用这样的模板:

var template = document.getElementById(templateid).innerHTML;
var newHtml = Mustache.render(template, {
    TITLE: some_var_with_title,
    KEYWORD: some_var_with_keyword,
    CONTENT: some_var_with_content,
    ID: some_var_with_id
});
document.getElementById('sample').innerHTML = newHtml;

如果您从Ajax调用中获取JSON,这尤其有效 - 您可以直接将其传递给Mustache.render()调用。

轻微的变化允许在每个浏览器或服务器上运行相同的模板。有关详细信息,请参阅https://github.com/janl/mustache.js

答案 9 :(得分:0)

试试这个:http://json2html.com/

它也支持复杂的JSON对象。

答案 10 :(得分:-2)

var template = "<div id='sample'><h4>%VAR%</h4><p>Text text %VAR% text</p><p>%VAR%</p><img src="images/%VAR%/1.jpg" /></div>";

var replace = function(temp,replace){
temp = temp.split('%VAR%');
for(var i in replace){
          if(typeof temp[i] != 'undefined'){
            temp[i] = temp[i] + replace[i];
          }
        }
   return temp.join('');
}

replace(template,['title','keyword','content','id'])