Как передать шаблон строки в функцию

244
27 сентября 2017, 12:36

Есть такой код:

function func(name, str) {
    var newStr = '`' + str + '`';
    return newStr;
}
var firstName = 'Mark';
var str = 'hi ${name}';
var f = func.bind(null, firstName);
console.log(f(str));

Вывод сейчас:

hi ${name}

Как нужно:

hi Mark

Как правильно передавать шаблонные строки в функции?

Answer 1

Такого нормально сделать нельзя.

Правильно будет передавать не шаблон, а функцию, заполняющую этот шаблон:

function hiTo(name) { 
  return `Hi ${name}`; 
} 
 
var firstName = 'Mark'; 
var f = hiTo.bind(null, firstName); 
console.log(f());

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

function hiTo(args, template) { 
  return template.replace(/\$\{(\w+)\}/g, (m,n) => args[n] || m); 
} 
 
var firstName = 'Mark'; 
var f = hiTo.bind(null, {name: firstName}); 
 
console.log(f('Hi ${name}')); 
console.log(f('Привет ${name}'));

Answer 2

Самый простой способ - передавать функцию вместо строки:

var strf = name => `Hi, ${name}!`; 
func("Mark", strf); 
 
function func(name, strf) { 
    console.log(strf(name)); 
}

В более сложных случаях вам потребуется new Function (но следите чтобы туда не попадали недоверенные строки!):

var str = 'Hi, ${name}!'; 
var strf = compile(str); 
func("Mark", strf); 
 
function func(name, strf) { 
    console.log(strf(name)); 
} 
 
function compile(str) { 
    return new Function("name", "return `" + str + "`"); 
}

Если даже имена переменных неизвестны заранее - придется воспользоваться устаревшей конструкцией with:

var str = 'Hi, ${name}!'; 
var strf = compile(str); 
func({ name: "Mark" }, strf); 
 
function func(data, strf) { 
    console.log(strf(data)); 
} 
 
function compile(str) { 
    return new Function("$data", "with ($data) return `" + str + "`"); 
}

Но лучше все же до такого не доводить и остановиться на первом варианте.

Answer 3

Простым таким способом, как у вас в вопросе, сделать так нельзя (или я не знаю как). Придется городить разные конструкции или костыли. Пример:

var template = function(tpl, args) { 
    var keys = Object.keys(args), 
        fn = new Function(...keys,  
          'return `' + tpl.replace(/`/g, '\\`') + '`'); 
    return fn(...keys.map(x => args[x])); 
}; 
 
 
function test() { 
    var myTpl = 'Hello ${str + "!"} and ${other.toUpperCase()}'; 
    console.log(template(myTpl, {str: 'foo', other: 'bar'})); 
} 
 
test();

взято с https://stackoverflow.com/a/41118285/6104996

Но как по мне, так проще для шаблонов в таком случае использовать банально replace по регулярке

Answer 4

Можно использовать eval

function func(name, str) { 
    var a = '`'+str+'`'; 
    var newStr = eval(a); 
    return newStr; 
} 
 
var firstName = 'Mark'; 
var str = 'hi ${name}'; 
var f = func.bind(null, firstName); 
console.log(f(str));

Но, как выяснилось, не нужно. Во-первых, не безопасно. Во-вторых, такой вариант не работает с обратными слешами в шаблоне. Они не экраниру.тся и шаблон все равно ломается в eval.

READ ALSO
Есть ли в javascript(nodejs) хеш-таблицы?

Есть ли в javascript(nodejs) хеш-таблицы?

Есть ли в javascript (или хотя бы в node js), рекомендуемый тип данных, аналогичный хеш таблицам, для хранения уникальности строк большого размера?

325
Анимация контуров фигур svg

Анимация контуров фигур svg

Добрый день, я делаю анимацию контуров, но есть один элемент который я не могу анимировать по контурам (странная кривая, смотрите ниже), поэтому...

299
Как заменить несколько слов в строке? [дубликат]

Как заменить несколько слов в строке? [дубликат]

Данный вопрос уже был задан и имеет решение:

211
Движение блока по параболе

Движение блока по параболе

С помощью jQuery animate делаю анимацию движения объекта, но нужно чтобы объект двигался по параболе, возможно ли это как-то сделать, задав лишь...

276