¿Cómo interpolar variables en cadenas en JavaScript, sin concatenación?

409

Sé que en PHP podemos hacer algo como esto:

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

Salida: "I pity the foo"

Me preguntaba si esto mismo también es posible en JavaScript. Usar variables dentro de cadenas sin usar concatenación: parece más conciso y elegante para escribir.

DMin
fuente

Respuestas:

696

Puede aprovechar Template Literals y usar esta sintaxis:

`String text ${expression}`

Los literales de plantilla están encerrados por la marca de retroceso (``) (acento grave) en lugar de comillas dobles o simples.

Esta característica se ha introducido en ES2015 (ES6).

Ejemplo

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

¿Qué tan limpio es eso?

Prima:

También permite cadenas de varias líneas en javascript sin escapar, lo cual es ideal para plantillas:

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

Soporte de navegador :

Como esta sintaxis no es compatible con navegadores antiguos (principalmente Internet Explorer), es posible que desee utilizar Babel / Webpack para transpilar su código en ES5 para asegurarse de que se ejecutará en todas partes.


Nota al margen:

A partir de IE8 +, puede usar el formato de cadena básico dentro console.log:

console.log('%s is %d.', 'Fifteen', 15);
// Fifteen is 15.
bformet
fuente
57
No se pierda el hecho de que la cadena de plantilla está delimitada con marcas de retroceso (`) en lugar de los caracteres de comillas normales. "${foo}"es literalmente $ {foo} `${foo}`es lo que realmente quieres
Hovis Biddle
1
¡También hay muchos transpiladores para convertir ES6 en ES5 para solucionar el problema de compatibilidad!
Nick
cuando cambio el valor aob. console.log ( Fifteen is ${a + b}.); no cambia dinámicamente siempre muestra que Quince tiene 15 años.
Dharan
168

Antes de Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, no, eso no era posible en JavaScript. Tendría que recurrir a:

var hello = "foo";
var my_string = "I pity the " + hello;
Sarfraz
fuente
2
Pronto será posible en javascript (ES6) con Cadenas de plantillas, vea mi respuesta detallada a continuación.
bformet
Es posible si desea escribir CoffeeScript, que en realidad ES javascript con una mejor sintaxis.
bformet
1
Gran grito para navegadores antiguos :)
Kirsty Marks
1
Me da pena el FOO !!! eso es genial
Adam Hughes
32

bueno, podrías hacer esto, pero no es especialmente general

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

Podría escribir fácilmente una función que haga esto de manera inteligente si realmente necesitara

Scott Evernden
fuente
Bastante decente, en realidad.
Sr. B
1
Esta respuesta es buena cuando necesita almacenar una cadena de plantilla en la base de datos y procesarla a pedido
Dima Escaroda
Buena, funciona bien. muy simple pero no vino a la mente.
Sam
13

Respuesta completa, lista para ser utilizada:

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

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

Llamar como

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

Para adjuntarlo a String.prototype:

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

Luego use como:

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

Puede usar esta función de JavaScript para hacer este tipo de plantillas. No es necesario incluir una biblioteca completa.

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"
    }
);

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

El uso de una función como argumento para la función String.replace () era parte de la especificación ECMAScript v3. Vea esta respuesta SO para más detalles.

Eric Seastrand
fuente
¿Es esto eficiente?
mmm
La eficiencia dependerá en gran medida del navegador del usuario, ya que esta solución delega el "trabajo pesado" de hacer coincidir la expresión regular y hacer reemplazos de cadenas a las funciones nativas del navegador. En cualquier caso, dado que esto está sucediendo en el lado del navegador, la eficiencia no es una gran preocupación. Si desea crear plantillas del lado del servidor (para Node.JS o similar), debe usar la solución de literales de plantilla ES6 descrita por @bformet, ya que probablemente sea más eficiente.
Eric Seastrand
9

Si te gusta escribir CoffeeScript puedes hacer:

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

CoffeeScript en realidad ES javascript, pero con una sintaxis mucho mejor.

Para obtener una descripción general de CoffeeScript, consulte esta guía para principiantes .

bformet
fuente
4

Si está intentando hacer interpolación para microtemplating, me gusta Moustache.js para ese propósito.

Joe Martinez
fuente
3

Escribí este paquete npm stringinject https://www.npmjs.com/package/stringinject que le permite hacer lo siguiente

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

que reemplazará {0} y {1} con los elementos de la matriz y devolverá la siguiente cadena

"this is a test string for stringInject"

o podría reemplazar marcadores de posición con claves de objeto y valores de esta manera:

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

"My username is tjcafferkey on Github" 
tjcafferkey
fuente
3

Yo usaría la marca de retroceso ''.

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

Pero si no sabes name1cuándo creas msg1.

Por ejemplo, si msg1proviene de una API.

Puedes 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'

Reemplazará ${name2}con su valor.

gturquais
fuente
2

No veo ninguna biblioteca externa mencionada aquí, pero Lodash tiene _.template() ,

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

Si ya está utilizando la biblioteca, vale la pena echarle un vistazo, y si no está utilizando Lodash, siempre puede elegir métodos de npm npm install lodash.template para que pueda reducir los gastos generales.

La forma mas simple -

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

También hay un montón de opciones de configuración:

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

Encontré los delimitadores personalizados más interesantes.

Mark Carpenter Jr
fuente
0

Crea un método similar al String.format()de Java

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

utilizar

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

Cita de paz de 2020:

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

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

Simplemente use:

var util = require('util');

var value = 15;
var s = util.format("The variable value is: %s", value)
Federico Caccia
fuente
-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
fuente
-2

var hello = "foo";

var my_string ="I pity the";

console.log (my_string, hola)

lalithya
fuente
1
Eso no responde la pregunta. Puede cerrar la sesión de ambas cadenas en una línea, pero eso no le da una nueva cadena que contenga ambas cadenas, que es lo que está pidiendo OP.
Max Vollmer el