web-dev-qa-db-ja.com

ES6テンプレートリテラルと連結文字列

Ecma-Script-6 template literalsには次のコードがあります

let person = {name: 'John Smith'};   
let tpl = `My name is ${person.name}.`;    
let MyVar="My name is "+ person.name+".";

console.log("template literal= "+tpl);  
console.log("my variable = "+MyVar);

出力は次のとおりです。

template literal= My name is John Smith.
my variable = My name is John Smith.

this はフィドルです。私は正確な違いを検索しようとしましたが、見つけることができませんでした。私の質問は、これら2つのステートメントの違いは何ですか、

  let tpl = `My name is ${person.name}.`;    

そして

  let MyVar = "My name is "+ person.name+".";

私はすでに文字列MyVarをここでperson.nameと連結できているので、テンプレートリテラルを使用するシナリオは何でしょうか?

58
Naeem Shaikh

質問の例のようにプレースホルダー(例:`Hello ${person.name}`)のみでテンプレートリテラルを使用している場合、結果は単なる文字列の連結と同じです。特に、複数行の文字列または'"の両方を含む文字列では、これらの文字をエスケープする必要がないため、主観的には見やすく、読みやすくなります。

読みやすさは優れた機能ですが、テンプレートについて最も興味深いのは タグ付きテンプレートリテラルです

let person = {name: 'John Smith'}; 
let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1];  
tag `My name is ${person.name}!` // Output: My name is JOHN SMITH!

この例の3行目では、tagという名前の関数が呼び出されます。テンプレート文字列の内容は複数の変数に分割され、tag関数の引数でアクセスできます:リテラルセクション(この例では、strArr[0]の値はMy name isです。 strArr[1]の値は!)および置換(John Smith)です。テンプレートリテラルは、tag関数が返すものに対して評価されます。

ECMAScript wiki は、入力の自動エスケープやエンコード、ローカリゼーションなど、考えられるいくつかのユースケースをリストしています。 msgという名前のタグ関数を作成して、My name isなどのリテラル部分を検索し、現在のロケールの言語、たとえばドイツ語への翻訳に置き換えることができます。

console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.

タグ関数によって返される値は、文字列である必要さえありません。この example のように、文字列を評価し、それをクエリセレクタとして使用してDOMノードのコレクションを返す$という名前のタグ関数を作成できます。

$`a.${className}[href=~'//${domain}/']`
76
kapex

ES6は、\ back-tick`を区切り文字として使用して、新しいタイプの文字列リテラルを作成します。これらのリテラルを使用すると、基本的な文字列補間式を埋め込むことができ、自動的に解析および評価されます。

let actor = {name: 'RajiniKanth', age: 68};

let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" +
  "<p>I am " + actor.age + " old</p>\n";

let newWayHtmlStr =
 `<p>My name is ${actor.name},</p>
  <p>I am ${actor.age} old</p>`;

console.log(oldWayStr);
console.log(newWayHtmlStr);

ご覧のとおり、文字列リテラルとして解釈される一連の文字の周りに..``を使用しましたが、${..}の形式の式はすぐに解析され、インラインで評価されます。

補間された文字列リテラルの利点の1つは、複数行に分割できることです。

var Actor = {"name" : "RajiniKanth"};

var text =
`Now is the time for all good men like ${Actor.name}
to come to the aid of their
country!`;
console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!

補間式

有効な式は、関数呼び出し、インライン関数式呼び出し、およびその他の${..}を含む、補間文字列lit‐ eralinterpo‐ lated string literals内に表示できます。

function upper(s) {
 return s.toUpperCase();
}
var who = "reader"
var text =
`A very ${upper( "warm" )} welcome
to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome
// to all of you READERS!

ここでは、who変数を"s"文字列と組み合わせた場合、who + "s"ではなく、内側の\ $ {who} s``補間された文字列リテラルが少し便利でした。また、メモを維持するために、補間された文字列リテラルは、lexically scopedではなく、dynamically scopedであるだけです。

function foo(str) {
 var name = "foo";
 console.log( str );
}
function bar() {
 var name = "bar";
 foo( `Hello from ${name}!` );
}
var name = "global";
bar(); // "Hello from bar!"

HTMLにtemplate literalを使用すると、煩わしさが減り、読みやすくなります。

昔ながらの方法:

'<div class="' + className + '">' +
  '<p>' + content + '</p>' +
  '<a href="' + link + '">Let\'s go</a>'
'</div>';

ES6を使用:

`<div class="${className}">
  <p>${content}</p>
  <a href="${link}">Let's go</a>
</div>`
  • 文字列は複数行にわたることができます。
  • 引用文字をエスケープする必要はありません。
  • 次のようなグループ化を避けることができます: '">'
  • プラス演算子を使用する必要はありません。

タグ付きテンプレートリテラル

template文字列にタグを付けることもできます。template文字列にタグを付けると、literalsと置換が結果値を返す関数に渡されます。

function myTaggedLiteral(strings) {
  console.log(strings);
}

myTaggedLiteral`test`; //["test"]

function myTaggedLiteral(strings,value,value2) {
  console.log(strings,value, value2);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5

ここでspread演算子を使用して、複数の値を渡すことができます。最初の引数(文字列と呼びます)は、すべてのプレーン文字列(補間式間のもの)の配列です。

その後、... gather/rest operatorを使用して、後続のすべての引数をvaluesという配列にまとめます。もちろん、上記の(value1, value2 etc)のように、stringsパラメーターに続く個別の名前付きパラメーターとして残すこともできます。

function myTaggedLiteral(strings,...values) {
  console.log(strings);
  console.log(values);    
}

let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5

値配列に集められたargument(s)は、文字列リテラルで見つかった既に評価された補間式の結果です。 tagged string literalは、補間が評価された後、最終的な文字列値がコンパイルされる前の処理ステップに似ており、リテラルから文字列を生成することをより細かく制御できます。 re-usable templatesの作成例を見てみましょう。

const Actor = {
  name: "RajiniKanth",
  store: "Landmark"
}

const ActorTemplate = templater`<article>
  <h3>${'name'} is a Actor</h3>
  <p>You can find his movies at ${'store'}.</p>

</article>`;

function templater(strings, ...keys) {
  return function(data) {
  let temp = strings.slice();
  keys.forEach((key, i) => {
  temp[i] = temp[i] + data[key];
  });
  return temp.join('');
  }
};

const myTemplate = ActorTemplate(Actor);
console.log(myTemplate);

生の文字列

タグ関数は、stringsと呼ばれるarrayと呼ばれる最初の引数を受け取ります。ただし、追加のデータが含まれています。すべての文字列の未処理の未加工バージョンです。次のように、.rawプロパティを使用して、これらの生の文字列値にアクセスできます。

function showraw(strings, ...values) {
 console.log( strings );
 console.log( strings.raw );
}
showraw`Hello\nWorld`;

ご覧のとおり、文字列のrawバージョンはエスケープされた\ nシーケンスを保持し、処理されたバージョンの文字列はエスケープされていない実際の改行のように処理します。 ES6には、文字列リテラルタグとして使用できる組み込み関数String.raw(..)が付属しています。単にstringsの未加工バージョンを通過します。

console.log( `Hello\nWorld` );
/* "Hello
World" */

console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"
14
Thalaivar

これは非常にクリーンで、コメントで述べられているように、他の言語の一般的な機能です。ナイスが見つけたもう一つのことは、改行で、文字列を書くときに非常に便利です。

let person = {name: 'John Smith', age: 24, greeting: 'Cool!' };

let usualHtmlStr = "<p>My name is " + person.name + ",</p>\n" +
                   "<p>I am " + person.age + " old</p>\n" +
                   "<strong>\"" + person.greeting +"\" is what I usually say</strong>";


let newHtmlStr = 
 `<p>My name is ${person.name},</p>
  <p>I am ${person.age} old</p>
  <p>"${person.greeting}" is what I usually say</strong>`;


console.log(usualHtmlStr);
console.log(newHtmlStr);
4
Rigotti

一方、私の答えは質問に直接対処するものではありません。配列結合を優先してテンプレートリテラルを使用する場合の1つの欠点を指摘することは、ある程度興味深いと思います。

私が持っているとしましょう

let patient1 = {firstName: "John", lastName: "Smith"};
let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};

したがって、一部の患者にはmiddleNameがあり、他の患者にはありません。

患者のフルネームを表す文字列が必要な場合

let patientName = `${patient1.firstName} ${patient1.middleName} ${patient1.lastName}`;

これは"John undefined Smith"になります

しかし、私がやった場合

let patientName = [patient1.firstName, patient1.middleName,  patient1.lastName].join(" ");

すると、これはただ"John Smith"になります

編集

General_Twyckenhamは、「」に結合すると「John」と「Smith」の間に余分なスペースが生じることを指摘しました。

これを回避するには、結合の前に偽の値を取り除くためのフィルターを使用します:[patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");

2
Dhruv Prakash