Jak interpolować zmienne w ciągach w JavaScript bez konkatenacji?


408

Wiem, że w PHP możemy zrobić coś takiego:

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

Wynik: "I pity the foo"

Zastanawiałem się, czy to samo jest również możliwe w JavaScript. Używanie zmiennych wewnątrz ciągów bez użycia konkatenacji - pisze bardziej zwięźle i elegancko.

Odpowiedzi:


695

Możesz skorzystać z literałów szablonów i użyć tej składni:

`String text ${expression}`

Literały szablonów są ujęte w tykanie (``) (poważny akcent) zamiast podwójnych lub pojedynczych cudzysłowów.

Ta funkcja została wprowadzona w ES2015 (ES6).

Przykład

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

Jak to jest miłe?

Premia:

Pozwala również na wieloliniowe ciągi w javascript bez zmiany znaczenia, co jest idealne dla szablonów:

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

Obsługa przeglądarki :

Ponieważ ta składnia nie jest obsługiwana przez starsze przeglądarki (głównie Internet Explorer), możesz użyć Babel / Webpack do transponowania swojego kodu do ES5, aby mieć pewność, że będzie działał wszędzie.


Dygresja:

Począwszy od IE8 +, możesz używać podstawowego formatowania ciągów wewnątrz console.log:

console.log('%s is %d.', 'Fifteen', 15);
// Fifteen is 15.

56
Nie przegap faktu, że ciąg szablonu jest ograniczony tylnymi paskami (`) zamiast zwykłych znaków cudzysłowu. "${foo}"jest dosłownie {foo} `${foo}`jest tym, czego naprawdę chcesz
Hovis Biddle

1
Ponadto istnieje wiele transpilatorów, które zamieniają ES6 w ES5, aby naprawić problem ze zgodnością!
Nick

kiedy zmieniam wartość a lub b. console.log ( Fifteen is ${a + b}.); nie zmienia się dynamicznie. zawsze pokazuje, że Piętnastka ma 15 lat.
Dharan,

168

Przed Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, nie, nie było to możliwe w javascript. Musisz uciekać się do:

var hello = "foo";
var my_string = "I pity the " + hello;

2
Wkrótce będzie to możliwe w javascript (ES6) z ciągami szablonów, zobacz moją szczegółową odpowiedź poniżej.
bformet

Jest to możliwe, jeśli lubisz pisać CoffeeScript, który faktycznie jest javascript o lepszej składni.
bformet

1
Świetny krzyk dla starszych przeglądarek :)
Kirsty Marks

1
Szkoda FOO !!! to świetnie
Adam Hughes


32

cóż, możesz to zrobić, ale nie jest to szczególnie ogólne

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

Możesz z łatwością napisać funkcję, która robi to inteligentnie, jeśli naprawdę tego potrzebujesz


Właściwie całkiem przyzwoite.
Pan B

1
Ta odpowiedź jest dobra, gdy trzeba przechowywać ciąg szablonu w bazie danych i przetwarzać go na żądanie
Dima Escaroda,

Dobry, działa dobrze. bardzo proste, ale nie przyszło mi do głowy.
Sam

13

Pełna odpowiedź, gotowa do użycia:

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

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

Zadzwoń jako

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

Aby dołączyć go do String.prototype:

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

Następnie użyj jako:

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

10

Możesz użyć tej funkcji javascript do tego rodzaju szablonów. Nie trzeba dołączać całej biblioteki.

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

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

Użycie funkcji jako argumentu funkcji String.replace () było częścią specyfikacji ECMAScript v3. Zobacz tę odpowiedź SO, aby uzyskać więcej informacji.


Czy to jest wydajne?
mmm

Wydajność zależeć będzie w dużej mierze od przeglądarki użytkownika, ponieważ to rozwiązanie deleguje „ciężkie podnoszenie” dopasowania wyrażenia regularnego i zastępowanie ciągów znaków do natywnych funkcji przeglądarki. W każdym razie, ponieważ dzieje się tak po stronie przeglądarki, wydajność nie jest tak dużym problemem. Jeśli chcesz szablonów po stronie serwera (dla Node.JS lub podobnych), powinieneś użyć rozwiązania literałów szablonów ES6 opisanego przez @bformet, ponieważ jest ono prawdopodobnie bardziej wydajne.
Eric Seastrand,



3

Napisałem ten pakiet npm stringinject https://www.npmjs.com/package/stringinject, który pozwala wykonać następujące czynności

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

który zastąpi {0} i {1} elementami tablicy i zwróci następujący ciąg

"this is a test string for stringInject"

lub możesz zastąpić symbole zastępcze kluczami i wartościami obiektów takimi jak:

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

"My username is tjcafferkey on Github" 

3

Użyłbym zaznaczenia wstecznego ``.

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

Ale jeśli nie wiesz, name1kiedy tworzysz msg1.

Na przykład, jeśli msg1pochodzi z interfejsu API.

Możesz użyć :

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'

Zastąpi ${name2}go jego wartością.


2

Nie widzę tu żadnych zewnętrznych bibliotek, ale Lodash ma _.template(),

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

Jeśli już korzystasz z biblioteki, warto to sprawdzić, a jeśli nie korzystasz z Lodash, zawsze możesz wybrać metody z npm, npm install lodash.templateaby zmniejszyć koszty ogólne.

Najprostsza forma -

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

Istnieje również wiele opcji konfiguracji -

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

Najbardziej interesujące są niestandardowe ograniczniki.


0

Utwórz metodę podobną do String.format()Java

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

posługiwać się

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

0

Cytat pokojowy 2020:

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

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

0

Po prostu użyj:

var util = require('util');

var value = 15;
var s = util.format("The variable value is: %s", value)

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

-2

var hello = "foo";

var my_string ="I pity the";

console.log (my_string, cześć)


1
To nie odpowiada na pytanie. Możesz wylogować oba ciągi w jednym wierszu, ale to nie daje nowego ciągu zawierającego oba ciągi, o co prosi OP.
Max Vollmer,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.