这个方法很好很强大,看代码:

function println(msg) { document.write((msg ? msg : '') + '<br />'); }

var s = '名称:{name}, 数量:{num}, 描叙:{desc}';
var o = { name: 'iPhone 3G', num: '8', desc: '很好' };
var r = YAHOO.lang.substitute(s, o);
println(r); // => 名称:iPhone 3G, 数量:8, 描叙:很好

注意o.desc的值可以包含各种字符,比如:

var s = '名称:{name}, 数量:{num}, 描叙:{desc}';
var o = { name: 'iPhone 3G', num: '8', desc: '{name}很好' };
var r = YAHOO.lang.substitute(s, o);
println(r); // => 名称:iPhone 3G, 数量:8, 描叙:iPhone 3G很好

可以发现,substitute方法会循环替换所有{key},这就产生了隐患:

var s = '名称:{name}, 数量:{num}, 描叙:{desc}';
var o = { name: 'iPhone 3G', num: '8', desc: '{desc}很好' };
var r = YAHOO.lang.substitute(s, o);
println(r); // => 恐怖的死循环

上面是发生在淘宝上的一个真实案例。我们的本意是只想替换一层,但substitute方法的递归导致了淘宝的list页面在某些特定情况下会陷入恐怖的死循环。知道了原因,解决办法就简单了。substitute支持第三个参数:

var s = '名称:{name}, 数量:{num}, 描叙:{desc}';
var o = { name: 'iPhone 3G', num: '8', desc: '{desc}很好' };
var r = YAHOO.lang.substitute(s, o, function(k, v) {
	v = v ? v : '';
	if(v.indexOf('{' + k + '}') >= 0) {
		v = v.replace('{', '{');
		v = v.replace('}', '}');
	}
	return v;
});
println(r); // => 名称:iPhone 3G, 数量:8, 描叙:{desc}很好

测试,一切工作得很好,不用担心死循环了。

若干天后,突然某个页面,运营部风急火燎的说又出错了:

检查数据,发现num少了引号:

var o = { name: 'iPhone 3G', num: 8, desc: '{desc}很好' };

没有引号导致num被解析成Number, 自然没有indexOf属性了。狂汗,立改之:

var s = '名称:{name}, 数量:{num}, 描叙:{desc}';
var o = { name: 'iPhone 3G', num: 8, desc: '{desc}很好' };
var r = YAHOO.lang.substitute(s, o, function(k, v) {
	v = String(v ? v : '');
	if(v.indexOf('{' + k + '}') >= 0) {
		v = v.replace('{', '{');
		v = v.replace('}', '}');
	}
	return v;
});
println(r); // => 名称:iPhone 3G, 数量:8, 描叙:{desc}很好

至此,终于风停雨消,可以安心睡觉了-.-
附上测试页面:yui_substitute_test.html