Comment interpoler des variables dans des chaînes en JavaScript, sans concaténation?

409

Je sais qu'en PHP, nous pouvons faire quelque chose comme ceci:

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

Production: "I pity the foo"

Je me demandais si cette même chose était également possible en JavaScript. Utiliser des variables à l'intérieur de chaînes sans utiliser de concaténation - il semble plus concis et élégant à écrire.

DMin
la source

Réponses:

698

Vous pouvez profiter des modèles de littéraux et utiliser cette syntaxe:

`String text ${expression}`

Les littéraux de modèle sont entourés d' une coche arrière (``) (accent grave) au lieu de guillemets doubles ou simples.

Cette fonctionnalité a été introduite dans ES2015 (ES6).

Exemple

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

Est-ce que c'est bien?

Prime:

Il permet également des chaînes de plusieurs lignes en javascript sans s'échapper, ce qui est idéal pour les modèles:

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

Prise en charge du navigateur :

Comme cette syntaxe n'est pas prise en charge par les navigateurs plus anciens (principalement Internet Explorer), vous souhaiterez peut-être utiliser Babel / Webpack pour transpiler votre code dans ES5 pour vous assurer qu'il s'exécutera partout.


Note latérale:

À partir d'IE8 +, vous pouvez utiliser le formatage de chaîne de base à l'intérieur console.log:

console.log('%s is %d.', 'Fifteen', 15);
// Fifteen is 15.
bformet
la source
57
Ne manquez pas le fait que la chaîne de modèle est délimitée par des graduations (`) au lieu de vos guillemets normaux. "${foo}"est littéralement $ {foo} `${foo}`est ce que vous voulez réellement
Hovis Biddle
1
Il existe également de nombreux transpilateurs pour transformer ES6 en ES5 afin de résoudre le problème de compatibilité!
Nick
quand je change une valeur a ou b. console.log ( Fifteen is ${a + b}.); ne change pas dynamiquement. il montre toujours que Fifteen a 15 ans.
Dharan
168

Avant Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, non, cela n'était pas possible en javascript. Vous devrez recourir à:

var hello = "foo";
var my_string = "I pity the " + hello;
Sarfraz
la source
2
Ce sera bientôt possible en javascript (ES6) avec les chaînes de modèles, voir ma réponse détaillée ci-dessous.
bformet
C'est possible si vous aimez écrire CoffeeScript, qui EST en fait javascript avec une meilleure syntaxe.
bformet
1
Grand cri pour les navigateurs plus anciens :)
Kirsty Marks
1
Je plains le FOO !!! c'est super
Adam Hughes
32

vous pouvez le faire, mais ce n'est pas général

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

Vous pouvez facilement écrire une fonction qui le fait intelligemment si vous en avez vraiment besoin

Scott Evernden
la source
Assez décent, en fait.
M. B
1
Cette réponse est bonne lorsque vous devez stocker la chaîne de modèle dans la base de données et la traiter à la demande
Dima Escaroda
Bon, ça marche bien. très simple mais ne m'est pas venu à l'esprit.
Sam
13

Réponse complète, prête à l'emploi:

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

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

Appelez en tant que

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

Pour l'attacher à String.prototype:

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

Ensuite, utilisez comme:

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

Vous pouvez utiliser cette fonction javascript pour effectuer ce type de modèle. Pas besoin d'inclure une bibliothèque entière.

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

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

L'utilisation d'une fonction comme argument de la fonction String.replace () faisait partie de la spécification ECMAScript v3. Voir cette réponse SO pour plus de détails.

Eric Seastrand
la source
Est-ce efficace?
mmm
L'efficacité dépendra en grande partie du navigateur de l'utilisateur, car cette solution délègue le «gros effort» de faire correspondre l'expression régulière et de remplacer les chaînes aux fonctions natives du navigateur. Dans tous les cas, puisque cela se produit de toute façon du côté du navigateur, l'efficacité n'est pas une préoccupation énorme. Si vous souhaitez créer des modèles côté serveur (pour Node.JS ou similaires), vous devez utiliser la solution de littéraux de modèle ES6 décrite par @bformet, car elle est probablement plus efficace.
Eric Seastrand
9

Si vous aimez écrire CoffeeScript, vous pouvez faire:

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

CoffeeScript EST en fait javascript, mais avec une bien meilleure syntaxe.

Pour un aperçu de CoffeeScript, consultez ce guide du débutant .

bformet
la source
4

Si vous essayez de faire une interpolation pour le microtemplage, j'aime Moustache.js à cet effet.

Joe Martinez
la source
3

J'ai écrit ce package npm stringinject https://www.npmjs.com/package/stringinject qui vous permet de faire ce qui suit

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

qui remplacera les {0} et {1} par les éléments du tableau et renverra la chaîne suivante

"this is a test string for stringInject"

ou vous pouvez remplacer les espaces réservés par des clés d'objet et des valeurs comme ceci:

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

"My username is tjcafferkey on Github" 
tjcafferkey
la source
3

J'utiliserais le back-tick ''.

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

Mais si vous ne savez pas name1quand vous créezmsg1 .

Par exemple si elle msg1provient d'une API.

Vous pouvez utiliser :

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'

Il remplacera ${name2}par sa valeur.

gturquais
la source
2

Ne voyez aucune bibliothèque externe mentionnée ici, mais Lodash a _.template(),

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

Si vous utilisez déjà la bibliothèque, cela vaut la peine de vérifier, et si vous n'utilisez pas Lodash, vous pouvez toujours choisir les méthodes de npm npm install lodash.templateafin de réduire les frais généraux.

Forme la plus simple -

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

Il y a aussi un tas d'options de configuration -

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

J'ai trouvé les délimiteurs personnalisés les plus intéressants.

Mark Carpenter Jr
la source
0

Créer une méthode similaire à celle String.format()de Java

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

utilisation

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

Citation de paix de 2020:

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

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

Utilisez simplement:

var util = require('util');

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

var hello = "foo";

var my_string ="I pity the";

console.log (my_string, bonjour)

lalithya
la source
1
Cela ne répond pas à la question. Vous pouvez vous déconnecter des deux chaînes sur une seule ligne, mais cela ne vous donne pas une nouvelle chaîne contenant les deux chaînes, ce que OP demande.
Max Vollmer