2013-04-18 45 views
2

當我經歷如何JavaScript Micro-Templating源代碼,我感到困惑的2個問題:JavaScript Micro-Templating如何工作?

  1. 爲什麼要用新功能而不是定義一個通用的功能?
  2. 爲什麼在新函數中沒有直接引用數據參數,但可以用正確的值替換。我期望使用數據[$ 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. 期望得到的語句,如那麼我們就可以用語句中使用。但是String.replace()總是返回字符串。我們期望一個符號而不是一個字符串。所以在這種情況下,evel型是最好的選擇。這就是我得到的。如果我錯了,請糾正我。
  2. 關鍵的第二個問題:
    • 鑽營功能
    • with語句

例子:

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); 

} 
+0

'new Function'是某種'eval',你需要這些模板。 – Bergi

+0

'與'是你的第二個問題的答案。它引用了一個名爲'obj'的正式參數,由包裝函數的'data'參數的值填充。 – raina77ow

+0

其實他在評論中說:「支持基本的咖喱」。他無法做到這一點,退出功能。 –

回答

0

爲什麼要使用新的功能而不是定義一個通用功能?

因爲它需要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(''); 
} 

爲什麼新功能沒有直接引用的數據參數,但可以用正確的值替換。我期望使用數據[$ 1]從數據中獲得正確的值。

由於data參數(如果存在的話)作爲obj參數到新fn函數傳遞,return子句(的代碼最後一行)右英寸然後您可以訪問其屬性(users),如變量with statement。如果數據不通過,新創建的功能將被退回,這樣,而不是

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

你也可以使用

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

這個概念被稱爲partial application,這裏錯誤地稱爲「鑽營」 (一個類似的,但非常不同的概念)。

+0

@IanJiang:你不明白什麼? – Bergi

+0

我不明白爲什麼要使用evel類型的函數。最後,我意識到爲了使用語句,我們需要使用符號而不是字符串。由於String.replace總是返回字符串。 –

+0

是的,模板代碼被讀取爲一個字符串,並且替換一些部分以使其成爲有效的js。然後,爲了進行評估,字符串需要變成一個可執行的函數 - 你可以用'var fn = new Function(argnames,bodyCode)來做什麼? FN(argvalues);'。 'eval'也可能已經被使用了,但是這需要在每次調用時解析字符串,而不是一次。 – Bergi