如果密钥不存在,则使用默认值进行插值
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'}}));
我在 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'}}));