模版替换技术

进入主题之前先介绍一种创建函数的新方法:new Function()

我们来创建一个函数,名字为foo

function foo(a, b){
	return a + b;
}

这种方式是我们普遍使用的,但同样的,我们还可以使用JS语言内置的Function对象来创建这个函数

var foo = new Function('a', 'b', 'return a + b;');

其实这两种写法在JS引擎看来是同一种,因为第一种会被转换为第二种,只不过第一种可读性更好而已。


例子说完了,来看下API:

/**
 * 函数名称为 funName
 * @param {String} p1 第一个参数名称
 * @param {String} p2 第二个参数名称
 * ...
 * @param {String} body 函数体
 */
var funName = new Function(p1, p2, ..., pn, body);


需要注意的是,p1 到 pn 是参数名称的列表,但 p1 不仅能代表一个参数,也可以是一个逗号隔开的参数列表,所以下面的定义是等价的:

new Function('a', 'b', 'c', 'return a + b + c;');
new Function('a, b', 'c', 'return a + b + c;');
new Function('a, b, c', 'return a + b + c;');


现在进入正题,我在John Resig的博客里发现了这个函数:

// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
	var cache = {};
  
	this.tmpl = function tmpl(str, data){
		// 查找非单词字符,如<>,没找到表示是ID,找到了表示是模板文本
		var fn = !/\W/.test(str) ?
			// 缓存模板
			cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) :
      
			// Generate a reusable function that will serve as a template
			// generator (and which will be cached).
			new Function("obj",
				"var p=[],print=function(){p.push.apply(p,arguments);};" +

				// Introduce the data as local variables using with(){}
				"with(obj){p.push('" +

				// Convert the template into pure JavaScript
				str
				  .replace(/[\r\t\n]/g, " ")
				  .split("<%").join("\t")
				  .replace(/((^|%>)[^\t]*)'/g, "$1\r")
				  .replace(/\t=(.*?)%>/g, "',$1,'")
				  .split("\t").join("');")
				  .split("%>").join("p.push('")
				  .split("\r").join("\\'")
				
				+ "');}return p.join('');");
    
		// Provide some basic currying to the user
		return data ? fn( data ) : fn;
	};
})();

 

核心是中间那个函数的逻辑,这里我写一个简单的模板:

var str = '<div class="<%=clsName%>">' +
				'<h1><%=title%></h1>' +
				'<p><%=content%></p>' +
			'</div>';
var result = tmpl(str);
console.log(result);

结果为:

function anonymous(obj) {
	var p = [], print = function(){ p.push.apply(p, arguments); };
	with(obj){
		p.push('<div class="', clsName, '"><h1>', title, '</h1><p>', content, '</p></div>');
	}
	return p.join('');
}

到此, 相信大家都知道这个函数做了什么事了。


作者最后分享了一个查找替换的小技巧,通常我们会用str.replace(/match/g, 'replace'),但是性能上还有一种更好的:

  str.split('match').join('replace');

posted @ 2011-12-04 15:30  越己  阅读(369)  评论(0编辑  收藏  举报