JavaScript/文字列
JavaScriptにおいて、文字列(もじれつ、string)とは文字の連続です。 JavaScriptには内容の書き換え不能なプリミティブの文字列と、そのラッパーオブジェクトのStringオブジェクトが存在し文字列に関するプロパティとメソッドを提供します。 JavaScriptの文字列は内部的にはUTF-16で符号化されています。
文字列リテラル
[編集]文字列はシングルクオート、ダブルクオート、またはバッククオートで囲まれた文字列リテラルとして表されます。たとえば、以下のように文字列を宣言することができます。
const str1 = 'Hello, World!'; // シングルクオートで囲まれた文字列 const str2 = "Hello, World!"; // ダブルクオートで囲まれた文字列 const str3 = `Hello, World!`; // バッククオートで囲まれた文字列
バッククオートで囲まれた文字列は、テンプレート文字列と呼ばれる特別な種類の文字列であり、変数や式を埋め込むことができます。たとえば、以下のようにテンプレート文字列を使用することができます。
const name = 'Alice'; const age = 25; const str = `My name is ${name} and I am ${age} years old.`; console.log(str); // "My name is Alice and I am 25 years old."
エスケープシーケンス
[編集]JavaScriptでは、文字列中に特殊な文字を含めたい場合に、エスケープシーケンスと呼ばれる特殊な文字列を使用することができます。エスケープシーケンスはバックスラッシュ \
の後に続く文字で構成されます。以下は、よく使われるエスケープシーケンスの例です。
\'
: シングルクオート\"
: ダブルクオート\\
: バックスラッシュ\n
: 改行\r
: キャリッジリターン\t
: タブ\b
: バックスペース\f
: フォームフィード
以下は、エスケープシーケンスを使用した文字列の例です。
const str1 = 'She said, "I\'m going home."'; // シングルクオートとダブルクオートを含む文字列 const str2 = "He said, \"Let's go!\""; // ダブルクオートとシングルクオートを含む文字列 const str3 = "C:\\Users\\Desktop\\file.txt"; // バックスラッシュを含むファイルパス文字列 const str4 = "Hello\nworld!"; // 改行を含む文字列 const str5 = "Hello\tworld!"; // タブを含む文字列
また、Unicodeエスケープシーケンスを使用して、Unicodeコードポイントを表すこともできます。Unicodeエスケープシーケンスは、\u
の後に4桁の16進数で表されるコードポイントを指定することで表現されます。たとえば、以下のようにUnicodeエスケープシーケンスを使用することができます。
const str = '\u3042\u3044\u3046'; // あいう
JavaScriptのエスケープシーケンスの一覧 文字 意味 ISO/IEC 8859-1エスケープシーケンス Unicodeエスケープシーケンス \b バックスペース \x08 \u0008 \t タブ \x09 \u0009 \n 改行 \x0A \u000A \v 垂直タブ \x0B \u000B \f 改ページ \x0C \u000C \r 復帰 \x0D \u000D \" " \x22 \u0022 \' ' \x27 \u0027 \\ バックスラッシュ \x5C \u005C \XXX ISO/IEC 8859-1エスケープシーケンス(八進法) \x00-\xFF \u0000-\u00FF \xXX ISO/IEC 8859-1エスケープシーケンス(十六進法) \x00-\xFF \u0000-\u00FF \uXXXX Unicodeエスケープシーケンス(十六進法) \x00-\xFF \u0000-\uFFFF
JavaScriptによる文字列の改行やタブなどのエスケープシーケンスがconsole.logメソッドやconsole.logなど一部のメソッドでしか動作しないかのように見えます。 これはHTML文書では内容がフィリング(詰め込み)されるため改行やタブは空白と同じ効果だからです。 このため、document.writeメソッドやdocument.writelnメソッドあるいはinnerHTMLプロパティではエスケープシーケンスのが作用していることを確認できません。 ISO/IEC 8859-1エスケープ文字では\x00から\xFFまでの文字を表すことができます。Unicodeエスケープ文字では\u0000から\uFFFFまでの文字を表すことができます。 JavaScriptでは互換性のためサロゲートペアの文字列をサポートしメソッドとサポートしている構文があるので使用にあたっては注意が必要です。特に絵文字はサロゲートペアなのでサポートしている構文を使うよう心がけて下さい(String.fromCharCodeやString.prototype.charCodeAtなどのメソッドはサロゲートペアに対応していませんが、スプレッド構文はサロゲートペア4バイトを正しく1文字と扱えます)。
String
[編集]Stringオブジェクトには文字列に関するプロパティとメソッドが提供されています。
const str = new String("Hello, world!"); console.log( str.length ); // "13" とコンソールに表示 -- 文字列の長さ
Stringオブジェクトでは文字列に関するさまざまなメソッドが提供されています。 文字列は自動的にStringオブジェクトのインスタンスに変換されるので、文字列でメソッドを使うことが出来る(ように見えます)。このようなクラスをプリミティブラッパークラスと呼びます。
プリミティブである文字列と、プリミティブラッパークラスであるStringオブジェクトは多くの場合意識しないでも問題有りませんが、いくつかの違いがあります。まず文字列は String 型ですが、 Stringオブジェクト は Object 型です。
const pstr = "Hello, world" const strw = new String("Hello, world!"); console.log( typeof pstr ); // "string" console.log( typeof strw ); // "object"
また、eval() の引数に文字列を渡した場合は文字列を評価しますが、Stringオブジェクトを渡した場合は評価せず文字列を返します。Stringオブジェクトから元の文字列を得るには valueOf() メソッドを使います。
const expr = "6 * 7"; const oexpr = new String(expr); console.log( eval(expr) ); // "42" console.log( eval(oexpr) ); // "6 * 7" console.log( eval(oexpr.valueOf()) ); // "42"
プロパティ
[編集]メソッド
[編集]文字の取得
[編集]文字列の個々の文字を取り出すには、charAtメソッドを使用します(帰ってくるのは文字、、ではなく長さ1の文字列です)。
const code = "Hello, world!".charAt(0); // "H"
文字列を配列として扱うこともできます。
const H = "Hello, world!"[0];
文字コード(UTF-16)を取得するにはcharCodeAtメソッドを使用します。
console.log( "Hello, world!".charCodeAt(0) ); // "72" とコンソールに表示 -- "H" のバイト表現
文字列の比較
[編集]文字列は数値と同じ比較演算子を使用して比較することができますが、Unicode 値を使用し(電話帳順ではなく)標準的な辞書順に基づいて比較されます。
if ( "abc" < "abd" ) { // "abc" が "abd" より小さいならば console.log(true); // "true" と警告 }
部分文字列
[編集]部分文字列(ぶぶんもじれつ、substring)とは、文字列の部分のことです。JavaScriptで "Hello, world!" から "world" の部分を取り出す処理の書き方はいくつかあります。まず、文字列の個々の文字を取得する処理についておさらいしておきましょう。
H | e | l | l | o | , | w | o | r | l | d | ! | |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
このように文字列の個々の文字には、インデックス (index) と呼ばれる添え字がふられています。インデックスは0から始まることに注意してください。また空白も一文字とみなすことにも注意してください。このとき、lengthプロパティで取得できる文字列の長さは13です。最後の文字のインデックスは文字列の長さより1小さくなります。charAtメソッドにインデックスを渡すと、個々の文字を取り出すことができます。
const letter = "Hello, world!".charAt(7);
"world" を取り出すにはsliceメソッドを使います。
const str = "Hello, world!".slice(7, 12);
第1引数に取り出す文字列 ("world") の最初の文字 ("w") のインデックス、第2引数に最後の文字の ("d") のインデックス + 1を渡します。第2引数は第1引数 + 部分文字列の長さと言い換えることもできます。まとめると、sliceメソッドは第1引数以上、第2引数未満の部分文字列を返します。
const world = "Hello, world!".substr(7, 5); // および const world = "Hello, world!".substring(7, 12);
Stringオブジェクトにはsliceメソッドのほかにも、substrメソッド、substringメソッド等があります。
ウェブコンテンツへ文字列表示
[編集]innerHTML
プロパティ使うと、JavaScript 側プログラムで用意した文字列などの変数を、HTMLとして表示することができます。
用途として、たとえば HTML入力フォームなどの結果に応じてJavaScriptのif文などの制御構造などを用いて表示したいメッセージを変更するなどが考えられます。
JavaScriptのコード内ではDIV要素やBR要素を操作するためにDOMが用意されています。
テンプレート・リテラル
[編集]ECMAScript 2015(ES6)から使えるようになった新機能として、文字列中に式を組込む「テンプレート・リテラル」(Template literals)があります。 提案書(proposal)では、「準リテラル」(Quasi-literals)あるいは「テンプレート文字列」(Template strings)と呼ばれていましたが[1]、ES2015言語仕様書では「テンプレート・リテラル」Template literals)と呼ばれるようになりました[2][3])。
テンプレート・リテラルのプレースホルダー
[編集]従来でも、"a = " + a + ", b = " + b + ", c = " + c + ";"
のような方法で変数の値を文字列に反映することは可能でしたが甚だ可読性を毀損していました[4]。
テンプレート・リテラルでは、`a = ${a}, b = ${b}, c = ${c}`
のようにバッククォート記号 `
で文字列全体を囲み、式は${ }
のようにドルマーク($)の先頭についた波括弧で囲み記載します。
この様にテンプレート・リテラルに埋め込まれた式をプレースホルダー(place holder)と呼ばれます。
- コード例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>テンプレート・リテラルの実験</title> </head> <body> <p id="myTarget">JavaScriptに対応したブラウザで表示して下さい。</p> </body> <script type"text/javascript"> const name = "タロウ"; const sex = "男" const mesg = ` ${name}は ${sex} です。` ; const elm = document.querySelector("#myTarget"); elm.innerHTML = mesg ; </script> </html>
- 結果
タロウは 男 です。
テンプレート・リテラルで複数行記載
[編集]テンプレート・リテラルは、" "
や' '
とは違い、複数行にまたがることが許されます。
const multi_lines = `この文字列はテンプレート・リテラルを使いました。 テンプレート・リテラルは + 演算子で複数の文字列をつなぐ必要なく、 複数行にまたがる文字列を記述できます。 他の言語の、ヒアドキュメントの様な使い方ができます。`; console.log(multi_lines); /* この文字列はテンプレート・リテラルを使いました。 テンプレート・リテラルは + 演算子で複数の文字列をつなぐ必要なく、 複数行にまたがる文字列を記述できます。 他の言語の、ヒアドキュメントの様な使い方ができます。 */
タグ付きテンプレート
[編集]テンプレート・リテラルの前に式(タグ)がある場合、タグ付きテンプレートと呼ばれます。 この場合タグ式(典型的には関数)がテンプレート・リテラルとともに呼び出され、出力する前にそのリテラルを操作することができます。
console.log`Text`;
テンプレート・リテラルは従来の文字列リテラルに比べて多機能ですが、従来の文字列リテラルにこの機能を追加しなかったのはなぜでしょうか?
答えは、互換性です。
テンプレート・リテラルに限らず、新機能をECMAScriptに追加する場合
従来からあるスクリプトの「意味が変わったり」(意味論の破壊)、「性能が落ちる」(機能性の毀損)ことがあってはならない。
という制約があります。このため従来の文字列リテラルにはテンプレート・リテラルの新機能を付与することはできませんでした。
附録
[編集]チートシート
[編集]// 文字列の生成 const str1 = "Hello, World!"; // ダブルクォーテーションで囲む const str2 = 'Hello, World!'; // シングルクォーテーションで囲む const str3 = `Hello, World!`; // バッククォーテーションで囲む // 特殊文字のエスケープ const str4 = "He said, \"I'm happy!\""; // ダブルクォーテーションで囲んだ中で、ダブルクォーテーションとシングルクォーテーションをエスケープ const str5 = 'He said, "I\'m happy!"'; // シングルクォーテーションで囲んだ中で、ダブルクォーテーションとシングルクォーテーションをエスケープ const str6 = `He said, "I'm happy!"`; // バッククォーテーションで囲んだ中で、ダブルクォーテーションとシングルクォーテーションをエスケープ // 変数の埋め込み const name = "John"; const age = 30; const str7 = `My name is ${name} and I am ${age} years old.`; // バッククォーテーションで囲んで、${} で変数を埋め込む // 文字列の長さ const str8 = "Hello"; const len = str8.length; // .length プロパティで文字列の長さを取得 // 文字列の切り出し const str9 = "Hello, World!"; const slice1 = str9.slice(0, 5); // .slice(start, end) メソッドで start から end-1 の範囲の文字列を取得 const slice2 = str9.slice(7); // .slice(start) メソッドで start 以降の文字列を取得 const slice3 = str9.slice(-6); // .slice(-n) メソッドで後ろから n 文字目以降の文字列を取得 // 文字列の検索 const str10 = "Hello, World!"; const index1 = str10.indexOf("o"); // .indexOf(searchString) メソッドで最初に見つかった searchString のインデックスを返す const index2 = str10.lastIndexOf("o"); // .lastIndexOf(searchString) メソッドで後ろから最初に見つかった searchString のインデックスを返す const index3 = str10.indexOf("o", 5); // .indexOf(searchString, fromIndex) メソッドで fromIndex 以降で最初に見
用語集
[編集]- 文字列 (String):文字列は文字の並びであり、ダブルクオート ("") もしくはシングルクオート () で囲われます。
- 文字列リテラル (String literal):文字列リテラルは、文字列を作成するために使用される文字列の直接的な表現です。
- 文字コード (Character code):各文字には、一意の数値コードが割り当てられています。これらのコードはUnicode規格に従って定義されています。
- Unicode:Unicodeは、世界のあらゆる文字を含む文字セットです。JavaScriptの文字列は、Unicode文字をサポートしています。
- エスケープシーケンス (Escape sequence):エスケープシーケンスは、文字列内で特殊な文字を表すために使用されます。例えば、改行を表すためには、\n を使用します。
- テンプレートリテラル (Template literal):テンプレートリテラルは、バッククオート (`) で囲まれた文字列であり、文字列内で式を評価するために ${} を使用することができます。
- テンプレートタグ (Template tag):テンプレートタグは、テンプレートリテラル内の式を処理するために使用される関数です。
- length プロパティ (length property):文字列の長さを返すプロパティです。
- charAt() メソッド:指定されたインデックスの位置にある文字を返すメソッドです。
- charCodeAt() メソッド:指定されたインデックスの位置にある文字のUnicode値を返すメソッドです。
- concat() メソッド:文字列を結合して新しい文字列を返すメソッドです。
- indexOf() メソッド:指定された文字列または文字の最初の出現位置を返すメソッドです。
- lastIndexOf() メソッド:指定された文字列または文字の最後の出現位置を返すメソッドです。
- slice() メソッド:文字列の一部分を抽出して新しい文字列を返すメソッドです。
- substr() メソッド:指定された位置から、指定された数の文字を抽出して新しい文字列を返すメソッドです。
- substring() メソッド:指定されたインデックスから、指定されたインデックスの前までの文字列を抽出して新しい文字列を返すメソッドです。
- split() メソッド:指定した区切り文字(デリミタ)で文字列を分割し、配列に格納します。
脚註
[編集]- ^ “A critical review of ECMAScript 6 quasi-literals - Human Who Codes” (2012年8月1日). 2022年7月1日閲覧。
- ^ Standard ECMA-262 6th Edition / June 2015 ECMAScript® 2015 Language Specification::11.8.6Template Literal Lexical Components
- ^ Template literals (Template strings)
They were called "template strings" in prior editions of the ES2015 specification.
- ^
["a = ", a, ", b = ", b, ", c = ", c, ";"].join("")
のように配列に文字リテラルと式を並べ join するスタイルが苦肉の策として使われることが有りました。