Можно ли создать шаблонную строку как обычную строку
let a="b:${b}";
затем преобразовать его в строку шаблона
let b=10;
console.log(a.template());//b:10
без eval
, new Function
а другие средства динамической генерации кода?
javascript
ecmascript-6
eval
template-strings
KOLANICH
источник
источник
Ответы:
Поскольку ваша строка шаблона должна
b
динамически (во время выполнения) получать ссылку на переменную, поэтому ответ: НЕТ, без динамической генерации кода обойтись невозможно.Но с
eval
этим все довольно просто:источник
a
строку , и это будет гораздо менее небезопасно:let tpl = eval('`'+a.replace(/`/g,'\\`')+'`');
. Я думаю, что более важным является то, чтоeval
мешает компилятору оптимизировать ваш код. Но я думаю, что это не имеет отношения к этому вопросу.eval
. Однако помните, что шаблонный литерал сам по себе является формойeval
. Два примера: var test =Result: ${alert('hello')}
; var test =Result: ${b=4}
; В итоге оба будут выполнять произвольный код в контексте скрипта. Если вы хотите разрешить произвольные строки, вы можете также разрешитьeval
.В моем проекте я создал нечто подобное с ES6:
ОБНОВЛЕНИЕ Я удалил зависимость от lodash, ES6 имеет эквивалентные методы для получения ключей и значений.
источник
ReferenceError: _ is not defined
. Это код не ES6, аlodash
конкретный, или ...?Что вы просите здесь:
в точности эквивалентен (с точки зрения мощности и, следовательно, безопасности)
eval
: способности взять строку, содержащую код, и выполнить этот код; а также возможность для исполняемого кода видеть локальные переменные в среде вызывающего.В JS нет способа, чтобы функция могла видеть локальные переменные в своем вызывающем объекте, если только эта функция не является
eval()
. ДажеFunction()
не могу этого сделать.Когда вы слышите, что в JavaScript появляется нечто, называемое «строками шаблонов», естественно предположить, что это встроенная библиотека шаблонов, такая как Mustache. Это не так. В основном это просто строковая интерполяция и многострочные строки для JS. Я думаю, что это будет распространенным заблуждением некоторое время, хотя. :(
источник
template is not a function
.Нет, не существует способа сделать это без динамической генерации кода.
Тем не менее, я создал функцию, которая превратит обычную строку в функцию, которая может быть снабжена картой значений, используя строки шаблона внутри.
Создать шаблон строки Gist
Использование:
Надеюсь, это кому-нибудь поможет. Если вы обнаружите проблему с кодом, пожалуйста, обновите Gist.
источник
var test = generateTemplateString('/api/${param1}/${param2}/')
console.log(test({param1: 'bar', param2: 'foo'}))
возврата шаблонов/api/bar//
TLDR: https://jsfiddle.net/w3jx07vt/
Кажется, все беспокоятся о доступе к переменным, почему бы просто не передать их? Я уверен, что не будет слишком сложно получить контекст переменной в вызывающей стороне и передать его. Используйте этот https://stackoverflow.com/a/6394168/6563504, чтобы получить реквизит от obj. Я не могу проверить тебя сейчас, но это должно сработать.
Проверено. Вот полный код.
источник
${}
символы. Попробуйте:/(?!\${)([^{}]*)(?=})/g
Проблема здесь в том, чтобы иметь функцию, которая имеет доступ к переменным своего вызывающего. Вот почему мы видим прямое
eval
использование для обработки шаблонов. Возможным решением было бы создание функции, принимающей формальные параметры, названные свойствами словаря, и вызывающей ее с соответствующими значениями в том же порядке. Альтернативный способ будет иметь что-то простое, как это:И для любого, кто использует компилятор Babel, нам нужно создать замыкание, которое запоминает среду, в которой он был создан:
источник
eval
потому, что он работает только с глобальнойname
переменнойvar template = function() { var name = "John Smith"; var message = "Hello, my name is ${name}"; this.local = new Function('return
'+ message +';')();}
new Function
не имеет доступа кvar name
вtemplate
функции.Здесь опубликовано много хороших решений, но ни одно еще не использует метод ES6 String.raw . Вот мой вклад. Он имеет важное ограничение в том, что он будет принимать свойства только от переданного объекта, то есть выполнение кода в шаблоне не будет работать.
parts: ["Hello, ", "! Are you ", " years old?"]
args: ["name", "age"]
obj
по имени свойства. Решение ограничено мелким одноуровневым отображением. Неопределенные значения заменяются пустой строкой, но допускаются другие ложные значения.parameters: ["John Doe", 18]
String.raw(...)
и верните результат.источник
.replace()
повторного вызова ?.replace()
, хотя :) Я думаю, что удобочитаемость важна, поэтому, используя собственные регулярные выражения, я пытаюсь назвать их, чтобы помочь разобраться во всем этом ...Похоже на ответ Даниэля (и суть Мейджера ), но более читабельно:
Примечание. Это немного улучшает оригинал s.meijer, поскольку он не будет соответствовать таким вещам, как
${foo{bar}
(регулярное выражение допускает использование только фигурных скобок внутри${
и}
).ОБНОВЛЕНИЕ: меня попросили привести пример с использованием этого, так что здесь вы идете:
источник
/\$\{(.*?)(?!\$\{)\}/g
(для обработки фигурных скобок гнезда). У меня есть рабочее решение, но я не уверен, что оно такое же портативное, как у вас, поэтому я хотел бы посмотреть, как это должно быть реализовано на странице. Мой также используетeval()
.eval
делает вас гораздо более открытым для возможных ошибок, которые могут вызвать проблемы с безопасностью, в то время как все, что делает моя версия, - это поиск свойства объекта по разделенному точками пути, который должен быть безопасным.Вы можете использовать прототип строки, например
Но ответить на исходный вопрос никак нельзя.
источник
Мне понравился ответ s.meijer и я написал свою версию на основе его:
источник
Мне понадобился этот метод с поддержкой Internet Explorer. Оказалось, что обратные галочки не поддерживаются даже IE11. Также; использование
eval
или его эквивалентFunction
не чувствует себя хорошо.Для того, кто замечает; Я также использую обратные пометки, но они удаляются компиляторами, такими как babel. Методы, предложенные другими, зависят от них во время выполнения. Как сказано ранее; это проблема в IE11 и ниже.
Так вот что я придумал:
Пример вывода:
источник
eval('`' + taggedURL + '`')
просто не работает.eval
. Что касается литералов шаблона: спасибо, что снова указали на это. Я использую Babel для переноса своего кода, но моя функция по-прежнему не будет работать, по-видимому AndreВ настоящее время я не могу комментировать существующие ответы, поэтому я не могу напрямую комментировать превосходный ответ Брайана Рейнора. Таким образом, этот ответ будет обновлять свой ответ с небольшой коррекцией.
Короче говоря, его функция не может фактически кэшировать созданную функцию, поэтому она всегда будет воссоздана, независимо от того, видел ли он шаблон раньше. Вот исправленный код:
источник
@Mateusz Moska, решение отлично работает, но когда я использовал его в React Native (режим сборки), он выдает ошибку: недопустимый символ '`' , хотя он работает, когда я запускаю его в режиме отладки.
Поэтому я записал свое собственное решение с помощью регулярных выражений.
Демо: https://es6console.com/j31pqx1p/
ПРИМЕЧАНИЕ. Так как я не знаю причину проблемы, я поднял тикет в реактивном репозитории https://github.com/facebook/react-native/issues/14107 , чтобы они могли исправить / направить меня примерно так же :)
источник
Все еще динамичный, но кажется более управляемым, чем просто использование голого eval:
https://repl.it/IdVt/3
источник
Это решение работает без ES6:
Примечание:
Function
конструктор всегда создается в глобальной области видимости, что потенциально может привести к тому, что глобальные переменные будут перезаписаны шаблоном, напримерrender("hello ${ someGlobalVar = 'some new value' }", {name:'mo'});
источник
Так как мы изобретаем колесо для чего-то, что было бы прекрасной функцией в javascript.
Я использую
eval()
, который не является безопасным, но JavaScript не является безопасным. Я с готовностью признаю, что я не очень хорошо разбираюсь в javascript, но у меня была потребность, и мне нужен был ответ, поэтому я его нашел.Я решил стилизовать свои переменные с помощью,
@
а не с$
, особенно потому, что я хочу использовать многострочную функцию литералов без оценки, пока она не будет готова. Так что переменный синтаксис@{OptionalObject.OptionalObjectN.VARIABLE_NAME}
Я не эксперт по javascript, поэтому я бы с удовольствием посоветовался по улучшению, но ...
Очень простая реализация следует
В моей реальной реализации я выбрал использование
@{{variable}}
. Еще один набор скобок. Абсурдно вряд ли столкнется с этим неожиданно. Регулярное выражение для этого будет выглядеть/\@\{\{(.*?)(?!\@\{\{)\}\}/g
Чтобы было легче читать
Если вы не сталкивались с регулярным выражением, довольно безопасное правило , чтобы избежать все не алфавитно-цифровой символ, а не когда - либо без необходимости избежать букв , как многие уцелевшие письма имеют особое значение для практически всех разновидностей регулярных выражений.
источник
Вам следует попробовать этот крошечный модуль JS от Andrea Giammarchi из github: https://github.com/WebReflection/backtick-template.
Демо (все следующие тесты возвращают true):
источник
Я сделал свое собственное решение, делая тип с описанием в качестве функции
и так делаем:
источник
Вместо использования eval лучше использовать регулярные выражения
Eval это не рекомендуется и крайне не рекомендуется, поэтому, пожалуйста, не используйте его ( mdn eval ).
источник