如果密钥不存在,则使用默认值进行插值

Interpolation with default if key not exists

我在 GitHub 上找到了一个字符串插值的简短片段,并将其缩短为:

var interpolate = function (tmpl, data) {
    return new Function('data', 'with(data){return \'' + 
        tmpl.replace(/{{\s*(.+?)\s*}}/g, '\'+()+\'') + '\';}')(data);
};

它适用于此:

interpolate('Hello {{user.name}}!', {user: {name: 'Admin'}});
// Hello Admin!

但是有两个结果我不喜欢:

interpolate('Hello {{user.firstname}}!', {user: {name: 'Admin'}});
// Hello undefined!

还有这个:

interpolate('Hello {{user.name}}!', {userinfo: {name: 'Admin'}});
// Uncaught ReferenceError: user is not defined(…)

如果密钥不存在,是否可以修改片段以使用默认值(空字符串)?

更新 现在我找到了满足我所有要求的解决方案:

function interpolate(tmpl, data, defaultValue, reg) {       
    return tmpl.replace(reg || /{{([^{}]*)}}/g, function(a, b) {
        try {
            return new Function('data', ['with(data){return ',b,' || \'',(defaultValue || ''),'\';}'].join(''))(data);
        }
        catch(e) {
            return defaultValue || '';                  
        }
    });
}

interpolate('Existing value: {{user.name}} - global value: {{Date.now()}} - undefined: {{user.age}} - exception: {{dat.haha}}', {user: {name: 'Admin'}}, '?');
// "Existing value: Admin - global value: 1441555682168 - undefined: ? - exception: ?"

欢迎提出建议!

假设您在字符串中只有一个占位符,以下内容有效:

var interpolate = function(s, data) {
  var RE= /{{\s*(.+?)\s*}}/,
      sp= s.match(RE)[1].split('.');  //example: ['user','name']

  sp.forEach(function(key) {
    data= data[key] || '';   //walk the object, defaulting to null string if undefined
  });
  
  return s.replace(RE, data);
};

console.log(interpolate('Hello {{user.name}}!', {user: {name: 'Admin'}}));

console.log(interpolate('Hello {{user.firstname}}!', {user: {name: 'Admin'}}));

console.log(interpolate('Hello {{user.name}}!', {userinfo: {name: 'Admin'}}));

Unfortunately expressions like {{Date.now()}} dont´t work with this solution

在那种情况下,您确实需要使用new Function()eval()

您可以将短路计算 (|| '') 添加到函数声明字符串中以避免未定义的对象属性,以及 try...catch 以避免未捕获的引用错误。

在下面的代码片段中,第二个示例的函数字符串最终看起来像这样:

with(data) try {
  return 'Hello '+(user.firstname || "")+'!';
} catch(e) {
  return 'Hello !'
}

片段:

var interpolate = function (tmpl, data) {
  var f= 'with(data) try{return \'' + 
           tmpl.replace(/{{\s*(.+?)\s*}}/g, ('\'+( || "")+\'') ) + '\';}'+
         'catch(e) {return \'' +
           tmpl.replace(/{{\s*(.+?)\s*}}/g, '') + "'"+
         '}';
  return new Function('data', f)(data);
};

console.log(interpolate('Hello {{user.name}}, it is currently {{Date()}}!', {user: {name: 'Admin'}}));

console.log(interpolate('Hello {{user.firstname}}!', {user: {name: 'Admin'}}));

console.log(interpolate('Hello {{user.name}}!', {userinfo: {name: 'Admin'}}));