web-dev-qa-db-fra.com

Comment puis-je effectuer une interpolation de chaîne en JavaScript?

Considérons ce code:

var age = 3;

console.log("I'm " + age + " years old!");

Existe-t-il d'autres moyens d'insérer la valeur d'une variable dans une chaîne, en dehors de la concaténation de chaîne?

373
Tom Lehman

Depuis ES6, vous pouvez utiliser template literals :

let age = 3;
console.log(`I'm ${age} years old!`);

P.S. Notez l'utilisation de backticks: ``.

290
Damjan Pavlica

tl; dr

Utilisez les littéraux de chaîne de modèle d'ECMAScript 2015, le cas échéant.

Explication

Il n'existe pas de moyen direct de le faire, conformément aux spécifications ECMAScript 5, mais ECMAScript 6 comporte chaînes de modèle , également appelées quasi-littéraux pendant la rédaction de la spéc. Utilisez-les comme ceci:

> var n = 42;
undefined
> `foo${n}bar`
'foo42bar'

Vous pouvez utiliser n'importe quelle expression JavaScript valide dans le {}. Par exemple:

> `foo${{name: 'Google'}.name}bar`
'fooGooglebar'
> `foo${1 + 3}bar`
'foo4bar'

L'autre chose importante est que vous n'avez plus à vous soucier des chaînes multilignes. Vous pouvez les écrire simplement comme

> `foo
...     bar`
'foo\n    bar'

Remarque: J'ai utilisé io.js v2.4.0 pour évaluer toutes les chaînes de modèle présentées ci-dessus. Vous pouvez également utiliser la dernière version de Chrome pour tester les exemples ci-dessus.

Remarque: Les spécifications de l'ES6 sont maintenant finalisées , mais n'ont pas encore été mises en œuvre par tous les principaux navigateurs. 
Selon les pages de Mozilla Developer Network , cela sera implémenté pour le support de base à partir des versions suivantes: Firefox 34, Chrome 41, Internet Explorer 12. Si vous êtes un utilisateur d'Opera, Safari ou Internet Explorer et êtes curieux à ce sujet maintenant, ce banc d’essai } peut être utilisé pour jouer jusqu’à ce que tout le monde obtienne le soutien nécessaire.

216
thefourtheye

Douglas Crockford's JavaScript correctif inclut une fonction String.prototype.supplant. Il est court, familier et facile à utiliser:

String.prototype.supplant = function (o) {
    return this.replace(/{([^{}]*)}/g,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

// Usage:
alert("I'm {age} years old!".supplant({ age: 29 }));
alert("The {a} says {n}, {n}, {n}!".supplant({ a: 'cow', n: 'moo' }));

Si vous ne souhaitez pas modifier le prototype de String, vous pouvez toujours l'adapter pour qu'il soit autonome ou le placer dans un autre espace de noms, ou autre.

182
Chris Nielsen

Attention: évitez tout système de gabarit qui ne vous permettrait pas d'échapper à ses propres délimiteurs. Par exemple, il n’existe aucun moyen de générer ce qui suit à l’aide de la méthode supplant() mentionnée ici.

"J'ai 3 ans grâce à ma variable {age}."

Une interpolation simple peut fonctionner pour de petits scripts autonomes, mais vient souvent avec ce défaut de conception qui limitera toute utilisation sérieuse. Honnêtement, je préfère les modèles DOM, tels que:

<div> I am <span id="age"></span> years old!</div>

Et utilisez la manipulation jQuery: $('#age').text(3)

Alternativement, si vous êtes simplement fatigué de la concaténation de chaînes, il existe toujours une syntaxe alternative:

var age = 3;
var str = ["I'm only", age, "years old"].join(" ");
48
greg.kindel

Essayez sprintf . Par exemple:

vsprintf('The first 4 letters of the english alphabet are: %s, %s, %s and %s', ['a', 'b', 'c', 'd']);
22
NawaMan

Vous pouvez utiliser le système de template de Prototype si vous avez vraiment envie d'utiliser un marteau pour casser une noix

var template = new Template("I'm #{age} years old!");
alert(template.evaluate({age: 21}));
21
shuckster

J'utilise ce modèle dans beaucoup de langues quand je ne sais pas encore le faire correctement et que je veux juste avoir une idée rapidement:

// JavaScript
var stringValue = 'Hello, my name is {name}. You {action} my {relation}.'
    .replace(/{name}/g    ,'Indigo Montoya')
    .replace(/{action}/g  ,'killed')
    .replace(/{relation}/g,'father')
    ;

Bien que pas particulièrement efficace, je le trouve lisible. Cela fonctionne toujours et est toujours disponible:

' VBScript
dim template = "Hello, my name is {name}. You {action} my {relation}."
dim stringvalue = template
stringValue = replace(stringvalue, "{name}"    ,"Luke Skywalker")     
stringValue = replace(stringvalue, "{relation}","Father")     
stringValue = replace(stringvalue, "{action}"  ,"are")

TOUJOURS

* COBOL
INSPECT stringvalue REPLACING FIRST '{name}'     BY 'Grendel'
INSPECT stringvalue REPLACING FIRST '{relation}' BY 'Mother'
INSPECT stringvalue REPLACING FIRST '{action}'   BY 'did unspeakable things to'
15
Jefferey Cave

Vous pouvez facilement utiliser ES6 template string et transpiler vers ES5 en utilisant n’importe quel transpilar disponible comme babel.

const age = 3;

console.log(`I'm ${age} years old!`);

http://www.es6fiddle.net/im3c3euc/

9
Mohammad Arif

Voici une solution qui vous oblige à fournir un objet avec les valeurs. Si vous ne spécifiez pas d'objet en tant que paramètre, il utilisera par défaut des variables globales. Mais il vaut mieux s'en tenir au paramètre, il est beaucoup plus propre.

String.prototype.interpolate = function(props) {
    return this.replace(/\{(\w+)\}/g, function(match, expr) {
        return (props || window)[expr];
    });
};

// Test:

// Using the parameter (advised approach)
document.getElementById("resultA").innerText = "Eruption 1: {eruption1}".interpolate({ eruption1: 112 });

// Using the global scope
var eruption2 = 116;
document.getElementById("resultB").innerText = "Eruption 2: {eruption2}".interpolate();
<div id="resultA"></div><div id="resultB"></div>

6
Lucas Trzesniewski

Essayez kiwi , un module JavaScript léger pour l’interpolation de chaînes.

Tu peux faire

Kiwi.compose("I'm % years old!", [age]);

ou

Kiwi.compose("I'm %{age} years old!", {"age" : age});
6
zsong

utilisez ` ( Les accents graves sont également connus sous le nom de backtick ) au lieu de guillemets simples (') ou de guillemets doubles (") et du signe dollar/crochet entre ${ variable }

Par exemple:

console.log(
  `current date: ${new Date()}`
);

En savoir plus sur les modèles littéraux ici .

5
Hardik

Si vous voulez interpoler dans la sortie console.log, alors juste

console.log("Eruption 1: %s", eruption1);
                         ^^

Ici, %s est ce qu'on appelle un "spécificateur de format". console.log a ce type de support d'interpolation intégré.

4
user663031

Un autre sledgehammer: jquery-tmpl (modèle avec jQuery).

3
Jo Liss

En développant Greg Kindel deuxième réponse, vous pouvez écrire une fonction pour éliminer une partie de la passe-partout:

var fmt = {
    join: function() {
        return Array.prototype.slice.call(arguments).join(' ');
    },
    log: function() {
        console.log(this.join(...arguments));
    }
}

Usage:

var age = 7;
var years = 5;
var sentence = fmt.join('I am now', age, 'years old!');
fmt.log('In', years, 'years I will be', age + years, 'years old!');
2
James Ko

Je peux vous montrer avec un exemple:

function fullName(first, last) {
  let fullName = first + " " + last;
  return fullName;
}

function fullNameStringInterpolation(first, last) {
  let fullName = `${first} ${last}`;
  return fullName;
}

console.log('Old School: ' + fullName('Carlos', 'Gutierrez'));

console.log('New School: ' + fullNameStringInterpolation('Carlos', 'Gutierrez'));

1
shades3002

Supplant more for ES6 version du post de @Chris Nielsen.

String.prototype.supplant = function (o) {
  return this.replace(/\${([^\${}]*)}/g,
    (a, b) => {
      var r = o[b];
      return typeof r === 'string' || typeof r === 'number' ? r : a;
    }
  );
};

string = "How now ${color} cow? {${greeting}}, ${greeting}, moo says the ${color} cow.";

string.supplant({color: "brown", greeting: "moo"});
=> "How now brown cow? {moo}, moo, moo says the brown cow."
0
SoEzPz

Depuis ES6, si vous souhaitez effectuer une interpolation de chaîne dans des clés d'objet, vous obtiendrez un SyntaxError: expected property name, got '${' si vous procédez comme suit:

let age = 3
let obj = { `${age}`: 3 }

Vous devriez plutôt faire ce qui suit:

let obj = { [`${age}`]: 3 }
0
Yuxuan Chen

Interpolation flexible personnalisée:

var sourceElm = document.querySelector('input')

// interpolation callback
const onInterpolate = s => `<mark>${s}</mark>`

// listen to "input" event
sourceElm.addEventListener('input', parseInput) 

// parse on window load
parseInput() 

// input element parser
function parseInput(){
  var html = interpolate(sourceElm.value, undefined, onInterpolate)
  sourceElm.nextElementSibling.innerHTML = html;
}

// the actual interpolation 
function interpolate(str, interpolator = ["{{", "}}"], cb){
  // split by "start" pattern
  return str.split(interpolator[0]).map((s1, i) => {
    // first item can be safely ignored
          if( i == 0 ) return s1;
    // for each splited part, split again by "end" pattern 
    const s2 = s1.split(interpolator[1]);

    // is there's no "closing" match to this part, rebuild it
    if( s1 == s2[0]) return interpolator[0] + s2[0]
    // if this split's result as multiple items' array, it means the first item is between the patterns
    if( s2.length > 1 ){
        s2[0] = s2[0] 
          ? cb(s2[0]) // replace the array item with whatever
          : interpolator.join('') // nothing was between the interpolation pattern
    }

    return s2.join('') // merge splited array (part2)
  }).join('') // merge everything 
}
input{ 
  padding:5px; 
  width: 100%; 
  box-sizing: border-box;
  margin-bottom: 20px;
}

*{
  font: 14px Arial;
  padding:5px;
}
<input value="Everything between {{}} is {{processed}}" />
<div></div>
0
vsync

L'utilisation de la syntaxe de modèle échoue dans les anciens navigateurs, ce qui est important si vous créez du HTML pour un usage public. L'utilisation de la concaténation est fastidieuse et difficile à lire, en particulier si vous avez des expressions longues ou longues, ou si vous devez utiliser des parenthèses pour gérer des mélanges d'éléments de nombre et de chaîne (les deux utilisant l'opérateur +).

PHP développe les chaînes entre guillemets contenant des variables et même certaines expressions en utilisant une notation très compacte: $a="the color is $color";

En JavaScript, une fonction efficace peut être écrite pour supporter ceci: var a=S('the color is ',color);, en utilisant un nombre variable d'arguments. Bien que la concaténation ne présente aucun avantage dans cet exemple, lorsque les expressions deviennent plus longues, cette syntaxe devient plus claire. Vous pouvez également utiliser le signe dollar pour signaler le début d’une expression à l’aide d’une fonction JavaScript, comme en PHP.

D'un autre côté, écrire une fonction de contournement efficace pour fournir une extension de chaînes de caractères semblable à un modèle pour les navigateurs plus anciens ne serait pas difficile. Quelqu'un l'a probablement déjà fait.

Enfin, j'imagine que sprintf (comme en C, C++ et PHP) pourrait être écrit en JavaScript, bien que ce soit un peu moins efficace que ces autres solutions.

0
David Spector