2

当我浏览JavaScript 微模板源代码时,我对 2 个问题感到困惑:

  1. 为什么要使用new Function而不是定义一个通用函数?
  2. 为什么在new Function中没有直接引用data参数,而是可以替换为正确的值。我希望使用data[$1]从数据中获取正确的值。

编码:

(function(){
  var cache = {};

  this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    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;
  };
})();
  1. 期望得到这样的语句,"<div>",name,"</div>"然后我们可以使用 with 语句。但是 String.replace() 总是返回字符串。我们期望一个符号而不是一个字符串。所以在这种情况下,级别类型是最好的选择。这就是我得到的。请纠正我,如果我错了。
  2. 第二个问题的关键:
    • 柯里化函数
    • 与声明

例子:

function wrapperFn(data) {

    var fn = function anonymous(obj) {
    var p=[],
        print=function(){p.push.apply(p,arguments);};

    with(obj) {
        p.push('   <p>',name,'</p>   ');
    }

    console.log("p.join(''):", p.join(''));

    return p.join('');
    }

    return fn(data);

}
4

1 回答 1

0

为什么要使用 new Function 而不是定义一个通用函数?

因为它需要eval模板中的代码。通过这种花哨的替换,它将模板语言转换为有效的 JS 语句。然后那些(仍然是字符串)通过new Function. 例如,user_tmpl示例将变为

function(obj) {
    var p=[],
        print=function(){p.push.apply(p,arguments);};
    with(obj) {
        p.push('  ');
        for ( var i = 0; i < users.length; i++ ) {
            p.push('     <li><a href="',users[i].url,'">',users[i].name,'</a></li>   ');
        }
        p.push('');
    }
    return p.join('');
}

为什么在 new Function 中没有直接引用 data 参数,而是可以替换为正确的值。我希望使用 data[$1] 从数据中获取正确的值。

因为data参数(如果存在)作为obj参数传递给新fn函数,就在 return 子句(代码的最后一行)中。然后,您可以访问它的属性 ( users),如由于该with语句的变量。如果没有传递数据,则将返回新创建的函数,以便代替

 var res = tmpl("templname", data);

你也可以使用

 var tmplFn = tmpl("templname");
 var res = templFn(data);

这个概念被称为部分应用,这里错误地称为“currying”(一个相似但完全不同的概念)。

于 2013-04-18T11:18:29.727 回答