2013-04-18 3 views
2

Когда я иду через Как JavaScript Micro-Templating исходного кода, я запутался около 2 вопроса:Как работает микро-Templating JavaScript?

  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. Ключ ко второму вопросу:
    • функция карринг
    • с утверждением

Пример:

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

'with' является ответом на ваш второй вопрос. Он относится к формальному параметру с именем '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 аргумент (если он присутствует) передается в качестве параметра в новой функции fnobj, прямо в пункте возврата (последняя строка кода). Затем вы можете получить доступ к своим свойствам (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 var = new Function (argnames, bodyCode); п (argvalues); '. 'eval', возможно, также использовался, но это должно было бы анализировать строку для каждого вызова, а не только один раз. – Bergi

Смежные вопросы