Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient Javascript String Replacement

It looks like you want to use a template.

//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 ] : "";
        }
      );
}

Explanation of the code:

  • Expects templateid to be the id of an existing element.
  • Expects data to be an object with the data.
  • Uses two parameters to replace to do the substitution:
  • The first is a regexp that searches for all %keys% (or {keys} if you use the alternate version). The key can be a combination of A-Z, a-z, 0-9 and underscore _.
  • The second is a anonymous function that gets called for every match.
  • The anonymous function searches the data object for the key that the regexp found. If the key is found in the data, then the value of the key is returned and that value will be replacing the key in the final output. If the key isn't found, an empty string is returned.

Example of template:

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

Example of call:

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

You could probably adapt this code to do what you want:

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

let template = `Hey {firstName},
    
    You recently requested your password.
    login: {login}
    password: {password}
    
    If you did not request your password, please disregard this message.
    `;

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

You might also want to look into JavaScriptTemplates


Template Replacement

A quick and easy solution will be to use the String.prototype.replace method.
It takes a second parameter that can be either a value or a function:

function replaceMe(template, data) {
  const pattern = /{\s*(\w+?)\s*}/g; // {property}
  return template.replace(pattern, (_, token) => data[token] || '');
}

###Example:

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'
};

And call it like so:

replaceMe(html, data);

I doubt there will be anything more efficient. The alternative would be splitting it into parts and then concatenating, but I don't think that would be much efficient. Perhaps even less, considering that every concatenation results in a new string which has the same size as its operands.

Added: This is probably the most elegant way to write this. Besides - what are you worried about? Memory usage? It's abundant and Javascript has a decent memory manager. Execution speed? Then you must have some gigantic string. IMHO this is good.