【JavaScriptクイズ】第3問:長いテキストをスマートに整形する方法

2023/03/29に公開

JavaScriptの文法や便利な使い方について、気軽なクイズ形式で解説する記事を書いていきます。

今回のテーマは「文字列の整形」です。では、さっそく問題です!

問題

改行を含む長い文字列に、短い文字列を埋め込んで表示するJavaScriptのプログラムを作りました。

quiz.js
"use strict";

function storyOf(person1, person2) {
  return "むかしむかしあるところに、\n"
    + person1 + "と" + person2 + "がすんでいました。\n"
    + "あるひのこと、" + person1 + "はやまへしばかりに、\n"
    + person2 + "はかわへせんたくにいきましたとさ。\n"
    + "めでたしめでたし。";
}

console.log(storyOf("おじいさん", "おばあさん"));

このプログラムを実行すると、以下のような出力を得られます。

実行結果
むかしむかしあるところに、
おじいさんとおばあさんがすんでいました。
あるひのこと、おじいさんはやまへしばかりに、
おばあさんはかわへせんたくにいきましたとさ。
めでたしめでたし。

プログラムは正常に動作しましたが、次の2点が気になっています。

  • 何度も+で文字列をつなげる処理が、書きづらいし読みづらい
  • \nで改行を入れるのがめんどうだし、ときどき書き忘れそう

そこで、+\nを減らしたいのですが、どのような方法が考えられるでしょうか?

ヒントを見る?

JavaScriptでは文字列をダブルクオート("……")やシングルクオート('……')で表現しますが、バッククオート(`……`)を使う方法もあります。

答えを見る?

テンプレートリテラルを使えば、プログラムは次のように書けます。

quiz.js
"use strict";

function storyOf(person1, person2) {
  return `むかしむかしあるところに、
${person1}${person2}がすんでいました。
あるひのこと、${person1}はやまへしばかりに、
${person2}はかわへせんたくにいきましたとさ。
めでたしめでたし。`;
}

console.log(storyOf("おじいさん", "おばあさん"));

解説

バッククオート(`……`)で囲む書き方は「テンプレートリテラル」と呼ばれる、文字列を整形するのに便利な書式です。テンプレートリテラルには、次のような性質があります。

  • 複数行をまるごと文字列にできる(\nと書く代わりに、本当に改行すればいい)
  • 途中に式を埋め込める(${式}と書く)

式を埋め込めるのは、変数の値を埋め込めるという意味でもあります。${x}のように変数名を書けば、その値が入ります。具体的な使い方は、次の例を見れば分かるでしょう。

プログラム例
let x = 100;
let text = `「x」が${x}のとき、「x + 5」は${x + 5}です。`;
console.log(text);
実行結果
「x」が100のとき、「x + 5」は105です。

テンプレートリテラルを使う

問題のプログラムにあった以下の部分は……

  return "むかしむかしあるところに、\n"
    + person1 + "と" + person2 + "がすんでいました。\n"
    + "あるひのこと、" + person1 + "はやまへしばかりに、\n"
    + person2 + "はかわへせんたくにいきましたとさ。\n"
    + "めでたしめでたし。";

テンプレートリテラルを使って次のように書き換えられます。

  return `むかしむかしあるところに、
${person1}${person2}がすんでいました。
あるひのこと、${person1}はやまへしばかりに、
${person2}はかわへせんたくにいきましたとさ。
めでたしめでたし。`;

+\nがなくなりましたね。また、実際に作られる文字列に近い表現になっているので、プログラムを読むのも楽になったのではないかと思います。

インデントを揃えて書くには?

今回のような複数行にわたるテンプレートリテラルでは、周囲の行のインデント(字下げ)を無視した書き方になってしまうのが難点です。

ためしに次のようにすると、プログラムの見た目はきれいになりますが……

quiz.js(バグ)
"use strict";

function storyOf(person1, person2) {
  return `むかしむかしあるところに、
    ${person1}${person2}がすんでいました。
    あるひのこと、${person1}はやまへしばかりに、
    ${person2}はかわへせんたくにいきましたとさ。
    めでたしめでたし。`;
}

console.log(storyOf("おじいさん", "おばあさん"));

実行結果(バグ)
むかしむかしあるところに、
    おじいさんとおばあさんがすんでいました。
    あるひのこと、おじいさんはやまへしばかりに、
    おばあさんはかわへせんたくにいきましたとさ。
    めでたしめでたし。

このように、テンプレートリテラルの途中にインデントを入れると、空白部分もそのまま出力されてしまいます。

テンプレートリテラルを使いつつ、インデントもきれいに揃えてプログラムを書きたい場合は、少し工夫が必要です。例えば、次のようにする方法が考えられます。

quiz.js
"use strict";

function storyOf(person1, person2) {
  return [
    "むかしむかしあるところに、",
    `${person1}${person2}がすんでいました。`,
    `あるひのこと、${person1}はやまへしばかりに、`,
    `${person2}はかわへせんたくにいきましたとさ。`,
    "めでたしめでたし。"
  ].join("\n");
}

console.log(storyOf("おじいさん", "おばあさん"));

インデントが問題になるのはテンプレートリテラルが複数行ある場合なので、1行ずつバラバラにしてみました。これなら、インデントのための空白が文字列に入り込んでしまう心配はありません。

また、各行を配列に入れておき、joinで1つにつなげています。\nと書くのは1回だけですむので、書き忘れも減らせるのではないかと思います。

まとめ

今回は、JavaScriptの「テンプレートリテラル」について紹介しました。いかがでしたか?

テンプレートリテラルは、長いテキストを整形するのに便利です。テキストの合間に「式」を書くことで、好きな値をスマートに埋め込めます。もちろん、1行だけのテキストに使うこともできます。いろいろなテキストに、ぜひテンプレートリテラルを活用してみてください。

ちなみに、同様の文法やテクニックは、ほかのプログラミング言語にもみられます。JavaScriptのように値を埋め込む方法は、一般的には「文字列補間(string interpolation)」と呼ばれるものです。JavaScriptのテンプレートリテラルの使い方を覚えておけば、ほかの言語を勉強するときにも役に立ちそうですね。

なお、今回の問題は、下記のページにあるC言語の問題をJavaScript向けにアレンジしたものでした。

https://curiocube.team-aries.com/cquiz-q05/

よろしければ、下記の本もチェックしてみてください。JavaScriptとC言語を含む、10種類のプログラミング言語について取り上げています。

https://zenn.dev/teamariesdotcom/books/af56bae422969b

Discussion