Hoe kan ik tekenreeksinterpolatie in JavaScript uitvoeren?

Denk aan deze code:

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

Zijn er andere manieren om de waarde van een variabele in een string in te voegen, afgezien van stringconcatenatie?


Antwoord 1, autoriteit 100%

Sinds ES6 kunt u sjabloonletterwoorden gebruiken :

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

Antwoord 2, autoriteit 35%

tl;dr

Gebruik ECMAScript 2015’s Template String Literals, indien van toepassing.

Uitleg

Er is geen directe manier om dit te doen, volgens de ECMAScript 5-specificaties, maar ECMAScript 6 heeft sjabloonstrings, die tijdens het opstellen ook bekend stonden als quasi-literals van de spec. Gebruik ze als volgt:

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

U kunt elke geldige JavaScript-expressie gebruiken binnen de {}. Bijvoorbeeld:

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

Het andere belangrijke is dat u zich geen zorgen meer hoeft te maken over snaren met meerdere regels. Je kunt ze gewoon schrijven als

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

Opmerking: ik heb io.js v2.4.0 gebruikt om alle hierboven getoonde sjabloonreeksen te evalueren. U kunt ook de nieuwste Chrome gebruiken om de hierboven getoonde voorbeelden te testen.

Opmerking: ES6-specificaties zijn nu definitief, maar moeten nog door alle grote browsers worden geïmplementeerd.
Volgens de Mozilla Developer Network-pagina’s zal dit geïmplementeerd voor basisondersteuning vanaf de volgende versies: Firefox 34, Chrome 41, Internet Explorer 12. Als u een Opera-, Safari- of Internet Explorer-gebruiker bent en hier nu nieuwsgierig naar bent, dit testbed kan worden gebruikt om te spelen totdat iedereen hier ondersteuning voor krijgt.


Antwoord 3, autoriteit 29%

Douglas Crockford’s Remedial JavaScript bevat een String.prototype.supplant functie. Het is kort, vertrouwd en gemakkelijk te gebruiken:

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

Als je het prototype van String niet wilt veranderen, kun je het altijd aanpassen om het op zichzelf te laten staan, of het in een andere naamruimte plaatsen, of wat dan ook.


Antwoord 4, autoriteit 8%

Waarschuwing: vermijd elk sjabloonsysteem waarmee u niet aan zijn eigen scheidingstekens kunt ontsnappen. Er zou bijvoorbeeld geen manier zijn om het volgende uit te voeren met behulp van de hier vermelde supplant()-methode.

“Ik ben 3 jaar oud dankzij mijn {age} variabele.”

Eenvoudige interpolatie werkt misschien voor kleine op zichzelf staande scripts, maar gaat vaak gepaard met deze ontwerpfout die elk serieus gebruik zal beperken. Ik geef eerlijk gezegd de voorkeur aan DOM-sjablonen, zoals:

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

En gebruik jQuery-manipulatie: $('#age').text(3)

Als je gewoon genoeg hebt van het aaneenschakelen van strings, is er altijd een alternatieve syntaxis:

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

Antwoord 5, autoriteit 4%

Ik gebruik dit patroon in veel talen als ik nog niet weet hoe ik het goed moet doen en gewoon snel een idee wil hebben:

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

Hoewel niet bijzonder efficiënt, vind ik het leesbaar. Het werkt altijd en het is altijd beschikbaar:

' 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")

ALTIJD

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

Antwoord 6, autoriteit 3%

Je zou Prototype’s sjabloonsysteem kunnen gebruiken als je echt zin hebt om een ​​voorhamer te gebruiken om kraak een noot:

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

Antwoord 7, autoriteit 3%

Probeer sprintf bibliotheek (een complete open source JavaScript sprintf implementatie). Bijvoorbeeld:

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

vsprintf neemt een reeks argumenten en retourneert een opgemaakte tekenreeks.


Antwoord 8, autoriteit 2%

Je kunt eenvoudig ES6 template string gebruiken en transpileren naar ES5 met elke beschikbare transpilar zoals babel.

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

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


Antwoord 9

Als je wilt interpoleren in console.log uitvoer, dan gewoon

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

Hier is %s wat een “formaatspecificatie” wordt genoemd. console.log heeft dit soort interpolatie-ondersteuning ingebouwd.


Antwoord 10

Probeer kiwi, een licht- gewicht JavaScript-module voor string-interpolatie.

Je kunt doen

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

of

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

Antwoord 11

Hier is een oplossing waarvoor u een object met de waarden moet opgeven. Als u geen object als parameter opgeeft, gebruikt het standaard globale variabelen. Maar beter vasthouden aan het gebruik van de parameter, het is veel schoner.

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>

Antwoord 12

Uitbreidend op Greg Kindel’s tweede antwoord, kun je een functie schrijven om een ​​deel van de standaardtekst te elimineren:

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

Gebruik:

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!');

Antwoord 13

Ik kan je een voorbeeld laten zien:

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'));

Antwoord 14

Sinds ES6, als je stringinterpolatie in objectsleutels wilt doen, krijg je een SyntaxError: expected property name, got '${' als je zoiets doet als:

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

U moet in plaats daarvan het volgende doen:

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

Antwoord 15

Vervang meer voor ES6-versie van het bericht van @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."

Antwoord 16

Kon niet vinden wat ik zocht, en vond het toen –

Als je Node.js gebruikt, is er een ingebouwd utilpakket met een formaatfunctie die als volgt werkt:

util.format("Hello my name is %s", "Brent");
> Hello my name is Brent

Toevallig is dit nu ook ingebouwd in console.log-smaken in Node.js –

console.log("This really bad error happened: %s", "ReferenceError");
> This really bad error happened: ReferenceError

Antwoord 17

Het gebruik van sjabloonsyntaxis mislukt in oudere browsers, belangrijk als u HTML maakt voor openbaar gebruik. Het gebruik van aaneenschakeling is vervelend en moeilijk te lezen, vooral als je veel of lange uitdrukkingen hebt, of als je haakjes moet gebruiken om combinaties van getallen en tekenreeksen te verwerken (beide gebruiken de operator +).

PHP breidt reeksen tussen aanhalingstekens die variabelen en zelfs sommige uitdrukkingen bevatten uit met een zeer compacte notatie: $a="the color is $color";

In JavaScript kan een efficiënte functie worden geschreven om dit te ondersteunen: var a=S('the color is ',color);, met een variabel aantal argumenten. Hoewel er in dit voorbeeld geen voordeel is ten opzichte van aaneenschakeling, kan deze syntaxis duidelijker zijn wanneer de expressies langer worden. Of men kan het dollarteken gebruiken om het begin van een uitdrukking aan te geven met behulp van een JavaScript-functie, zoals in PHP.

Aan de andere kant zou het niet moeilijk zijn om een ​​efficiënte tijdelijke oplossing te schrijven om te voorzien in een sjabloonachtige uitbreiding van strings voor oudere browsers. Iemand heeft het waarschijnlijk al gedaan.

Ten slotte stel ik me voor dat sprintf (zoals in C, C++ en PHP) in JavaScript zou kunnen worden geschreven, hoewel het iets minder efficiënt zou zijn dan deze andere oplossingen.


Antwoord 18

Aangepaste flexibele interpolatie:

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>

Antwoord 19

Hoewel sjablonen waarschijnlijk het beste zijn voor het geval dat u beschrijft, kunt u, als u uw gegevens en/of argumenten in itereerbare/arrayvorm heeft of wilt hebben, String.raw.

String.raw({
  raw: ["I'm ", " years old!"]
}, 3);

Met de gegevens als een array kan men de spread-operator gebruiken:

const args = [3, 'yesterday'];
String.raw({
  raw: ["I'm ", " years old as of ", ""]
}, ...args);

Antwoord 20

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

U kunt de backticks “ en ES6 sjabloontekenreeks

gebruiken


Antwoord 21

Het eenvoudigste zou zijn

`my string ${VARIABLE}`

een minder efficiënte manier om dit te bereiken zou zijn

function format(str, ...params) {
  for(const param of params)
    str = str.replace("%", param);
   return str;
}

die kan worden gebruikt met

format("My % string", "interpolation")

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes