Como interpolar variáveis ​​em strings em JavaScript, sem concatenação?

409

Eu sei que em PHP podemos fazer algo assim:

$hello = "foo";
$my_string = "I pity the $hello";

Resultado: "I pity the foo"

Eu queria saber se essa mesma coisa é possível em JavaScript também. Usando variáveis ​​dentro de strings sem usar concatenação - parece mais conciso e elegante escrever.

DMin
fonte

Respostas:

696

Você pode tirar proveito dos Literais de Modelo e usar esta sintaxe:

`String text ${expression}`

Os literais de modelo são delimitados por back-tick (``) (acento grave) em vez de aspas duplas ou simples.

Esse recurso foi introduzido no ES2015 (ES6).

Exemplo

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b}.`);
// "Fifteen is 15.

Quão legal é isso?

Bônus:

Ele também permite seqüências de várias linhas em javascript sem escapar, o que é ótimo para modelos:

return `
    <div class="${foo}">
         ...
    </div>
`;

Suporte do navegador :

Como essa sintaxe não é suportada por navegadores mais antigos (principalmente o Internet Explorer), convém usar o Babel / Webpack para transpilar seu código no ES5 para garantir que ele seja executado em qualquer lugar.


Nota:

A partir do IE8 +, você pode usar a formatação básica de cadeias dentro console.log:

console.log('%s is %d.', 'Fifteen', 15);
// Fifteen is 15.
bformet
fonte
57
Não perca o fato de que a string do modelo é delimitada com back ticks (`) em vez de seus caracteres de aspas normais. "${foo}"é literalmente $ {foo} `${foo}`é o que você realmente quer
Hovis Biddle
1
Também existem muitos transpilers para transformar o ES6 em ES5 para corrigir o problema de compatibilidade!
Nick
quando altero o valor a ou b. console.log ( Fifteen is ${a + b}.); não mudou dinamicamente. ele sempre mostra Quinze é 15.
Dharan
168

Antes do Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, não era possível em javascript. Você teria que recorrer a:

var hello = "foo";
var my_string = "I pity the " + hello;
Sarfraz
fonte
2
Em breve será possível em javascript (ES6) com seqüências de caracteres de modelo, veja minha resposta detalhada abaixo.
precisa saber é
É possível se você quiser escrever o CoffeeScript, que na verdade é javascript com uma sintaxe melhor.
bformet
1
Ótimo grito para navegadores mais antigos :)
Kirsty Marks
1
Tenho pena do FOO !!! isso é ótimo
Adam Hughes
32

bem, você poderia fazer isso, mas não é esp geral

'I pity the $fool'.replace('$fool', 'fool')

Você pode escrever facilmente uma função que faça isso de forma inteligente se realmente precisar

Scott Evernden
fonte
Bastante decente, na verdade.
Mr. B
1
Esta resposta é boa quando você precisa de seqüência de loja modelo no banco de dados e processá-lo sob demanda
Dima Escaroda
Bom, funciona bem. muito simples, mas não veio à mente.
21419 Sam
13

Resposta completa, pronta para ser usada:

 var Strings = {
        create : (function() {
                var regexp = /{([^{]+)}/g;

                return function(str, o) {
                     return str.replace(regexp, function(ignore, key){
                           return (key = o[key]) == null ? '' : key;
                     });
                }
        })()
};

Ligar como

Strings.create("My firstname is {first}, my last name is {last}", {first:'Neo', last:'Andersson'});

Para anexá-lo ao String.prototype:

String.prototype.create = function(o) {
           return Strings.create(this, o);
}

Então use como:

"My firstname is ${first}".create({first:'Neo'});
mmm
fonte
10

Você pode usar esta função javascript para fazer esse tipo de modelagem. Não há necessidade de incluir uma biblioteca inteira.

function createStringFromTemplate(template, variables) {
    return template.replace(new RegExp("\{([^\{]+)\}", "g"), function(_unused, varName){
        return variables[varName];
    });
}

createStringFromTemplate(
    "I would like to receive email updates from {list_name} {var1} {var2} {var3}.",
    {
        list_name : "this store",
        var1      : "FOO",
        var2      : "BAR",
        var3      : "BAZ"
    }
);

Saída :"I would like to receive email updates from this store FOO BAR BAZ."

O uso de uma função como argumento para a função String.replace () fazia parte da especificação do ECMAScript v3. Veja esta resposta SO para mais detalhes.

Eric Seastrand
fonte
Isso é eficiente?
mmm
A eficiência dependerá em grande parte do navegador do usuário, pois essa solução delega o "trabalho pesado" de corresponder ao regex e fazer substituições de string às funções nativas do navegador. De qualquer forma, como isso está acontecendo no lado do navegador, a eficiência não é uma preocupação tão grande. Se você deseja modelos do lado do servidor (para Node.JS ou similares), use a solução literal de modelo ES6 descrita por @bformet, pois provavelmente é mais eficiente.
Eric Seastrand 5/07
9

Se você gosta de escrever CoffeeScript, pode fazer:

hello = "foo"
my_string = "I pity the #{hello}"

O CoffeeScript é realmente javascript, mas com uma sintaxe muito melhor.

Para uma visão geral do CoffeeScript, consulte este guia para iniciantes .

bformet
fonte
4

Se você está tentando fazer uma interpolação para microtemplating, eu gosto do Mustache.js para esse fim.

Joe Martinez
fonte
3

Eu escrevi este pacote npm stringinject https://www.npmjs.com/package/stringinject que permite que você faça o seguinte

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

que substituirá {0} e {1} pelos itens da matriz e retornará a seguinte string

"this is a test string for stringInject"

ou você pode substituir espaços reservados por chaves e valores de objetos da seguinte forma:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 
tjcafferkey
fonte
3

Eu usaria o back-tick ``.

let name1 = 'Geoffrey';
let msg1 = `Hello ${name1}`;
console.log(msg1); // 'Hello Geoffrey'

Mas se você não souber name1quando criar msg1.

Por exemplo, se msg1 de uma API.

Você pode usar :

let name2 = 'Geoffrey';
let msg2 = 'Hello ${name2}';
console.log(msg2); // 'Hello ${name2}'

const regexp = /\${([^{]+)}/g;
let result = msg2.replace(regexp, function(ignore, key){
    return eval(key);
});
console.log(result); // 'Hello Geoffrey'

Ele será substituído ${name2}por seu valor.

gturquais
fonte
2

Não veja nenhuma biblioteca externa mencionada aqui, mas a Lodash possui _.template(),

https://lodash.com/docs/4.17.10#template

Se você já está usando a biblioteca, vale a pena conferir e, se você não estiver usando o Lodash, poderá sempre escolher métodos da npm npm install lodash.templatepara reduzir as despesas gerais.

Forma mais simples -

var compiled = _.template('hello <%= user %>!');
compiled({ 'user': 'fred' });
// => 'hello fred!'

Também existem várias opções de configuração -

_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
var compiled = _.template('hello {{ user }}!');
compiled({ 'user': 'mustache' });
// => 'hello mustache!'

Achei delimitadores personalizados mais interessantes.

Mark Carpenter Jr
fonte
0

Crie um método semelhante ao String.format()Java

StringJoin=(s, r=[])=>{
  r.map((v,i)=>{
    s = s.replace('%'+(i+1),v)
  })
return s
}

usar

console.log(StringJoin('I can %1 a %2',['create','method'])) //output: 'I can create a method'
Emerson Barcellos
fonte
0

Citação de paz de 2020:

Console.WriteLine("I {0} JavaScript!", ">:D<");

console.log(`I ${'>:D<'} C#`)
MatrixRonny
fonte
0

Basta usar:

var util = require('util');

var value = 15;
var s = util.format("The variable value is: %s", value)
Federico Caccia
fonte
-1
String.prototype.interpole = function () {
    var c=0, txt=this;
    while (txt.search(/{var}/g) > 0){
        txt = txt.replace(/{var}/, arguments[c]);
        c++;
    }
    return txt;
}

Uso:

var hello = "foo";
var my_string = "I pity the {var}".interpole(hello);
//resultado "I pity the foo"
Abran Salas Molina
fonte
-2

var hello = "foo";

var my_string ="I pity the";

console.log (minha_string, olá)

lalithya
fonte
1
Isso não responde à pergunta. Você pode desconectar as duas seqüências em uma linha, mas isso não fornece uma nova sequência contendo as duas, que é o que o OP está solicitando.
precisa