Построить шаблонный литерал ES6 с функцией

1

У меня есть строка, которая содержит шаблонные литералы, но не является литералом шаблона из-за его динамического построения. Я хотел бы преобразовать его в шаблон "literal", не делая eval():

   // this is dynamically created by an algo:
   const vars = '${var1} ${var2}';
   const str = 'the result is ' + vars;

   // this works, but it nasty: 
   eval('result = '' + str + ''');

Я ищу доступ к внутреннему построителю шаблонов в духе класса RegExp, который можно использовать вместо стандартных реляционных слэшей регулярного выражения //:

   const myRegex = '^(\d+)$';
   new RegExp(myRegex);

Таким образом я мог бы сделать:

   const myStr = 'I want to be ${foo}';
   const foo = 99;
   const lit = new TemplateLiteral(myStr);
   console.log( lit.run() ); // I want to be 99
  • 0
    Одним из способов может быть использование токенизатора, например github.com/fuckingdigital/textator.
  • 0
    Было бы лучше ответить на этот вопрос, если бы мы знали больше об этом «динамическом создании» шаблона.
Показать ещё 1 комментарий
Теги:

2 ответа

3

Вы не можете "построить литерал". Это противоречие в терминах. Литерал - это синтаксис исходного кода, который компилируется в значение.

new RegExp(...) создает новый объект regexp, но не литерал регулярного выражения. Регламент REGExp - это когда вы буквально пишете /.../.

Точно так же строковый литерал буквально только тогда, когда вы пишете '...', "..." или '...' в коде. Вы можете построить строку - как правило, используя конкатенацию, но нет возможности построить строковый литерал.

EDIT: Быстрая и грязная:

function makeTemplate(template) {
  return new Function("return '" + template + "'");
}

const myStr = 'I want to be ${foo}';
const foo = 99;
const template = makeTemplate(myStr);
console.log(template());
// I want to be 99

Однако, в то время как new Function всегда лучше, чем eval, применяются обычные отказы в выполнении ненадежных строк.

Для более безопасной альтернативы см. Mustache.js или Pug.js (а не Pod, как я сказал в комментарии, извините), как ведущие библиотеки шаблонов JavaScript.

  • 0
    Вы правы, я прошу объект шаблона не буквальный, как объект RegExp . Как только я построю объект шаблона, я вызову run() . Я отредактирую вопрос для ясности.
  • 0
    Строковый литерал шаблона оценивается как строка, а не как шаблон. В JavaScript нет такой вещи, как «объект шаблона», кроме тех, которые созданы библиотекой, такой как Mustache.js или Pod.js.
Показать ещё 2 комментария
1

Ключевая проблема здесь заключается в том, что у вас есть в вашем комментарии в первом блоке кода:

это динамически создается алгоритмом

Если шаблон создан по алгоритму, ваши варианты:

  • Не используйте встроенную функцию шаблона, используйте любую из нескольких похожих библиотек шаблонов (или напишите сами)
  • Используйте eval или одного из его кузенов (возможно, new Function)

Динамические шаблоны шаблонов нельзя создавать динамически. Это литералы. :-)

Если бы мы знали больше о вашем алгоритме, мы могли бы помочь вам лучше. Например, вы могли бы создать алгоритм для создания функции, а затем вызвать эту функцию с информацией, которая может понадобиться:

function getVarsFormatter(var1First) {
    if (var1First) {
        return (var1, var2) => '${var1} ${var2}';
    } else {
        return (var1, var2) => '${var2} ${var1}';
    }
}

затем

const formatter = getVarsFormatter(flag);
const result = formatter("this is var1", "this is var2");

Живой пример:

function getVarsFormatter(var1First) {
    if (var1First) {
        return (var1, var2) => '${var1} ${var2}';
    } else {
        return (var1, var2) => '${var2} ${var1}';
    }
}

for (let n = 0; n < 6; ++n) {
  const formatter = getVarsFormatter(Math.random() < 0.5);
  const result = formatter("this is var1", "this is var2");
  console.log(result);
}
  • 0
    «Алго» загружает строки шаблона из внутреннего файла приложения.
  • 0
    @ojosilva - Тьфу. Боюсь, если отправной точкой является строка, определяющая шаблон (например, загруженный из файла), ваши единственные варианты - это два, которые я перечислил выше: использовать библиотеку шаблонов или использовать new Function двоюродного брата eval .
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню