文字列操作

【JavaScript】文字列切り出しの覚書

更新日:2023/04/21

自分、最近記憶力が低下してきたのか、JavaScriptで文字列を位置指定で部分文字列を切り出すメソッドを記憶できません。
毎回調査するのが面倒になってきたので、方法をまとめておきます。

 

切り出しメソッドは3つ

文字列から位置指定で部分文字列を切り出すメソッドは、3つあります。

メソッド名引数備考
substring()開始位置、終了位置マイナス値は0として扱う
slice()開始位置、終了位置開始位置がマイナスのとき
文字列長+開始位置から開始
substr()開始位置、長さ開始位置がマイナスのとき
文字列長+開始位置から開始
ブラウザーレガシー機能

 

substring()

substring()は、次のように定義されています。

substring()の定義>

String.prototype.substring ( start, end )
  • start:
    startは、次の計算が適用されます。
    1. 非数値のとき、start = 0
    2. start = min( max(start, 0), 文字列長 )
  • end:
    endは、次の計算が適用されます。
    1. undefined のとき、end = 文字列長
    2. 非数値のとき、end = 0
    3. end = min( max(end , 0), 文字列長 )

計算により start > end となった場合、値が交換されます。

■substring()の特徴
① 各値とも0から文字列長の範囲で丸められる。
② 第二引数を省略すると、文字列の最後まで切り出される。
③ 二つの引数は開始・終了というよりも、切り出す範囲ととらえるべき
文字位置は、0から開始です。単位はコードユニットです。
数値文字列は数値に変換されます。

実行例

console.log( "0123456789".substring( 2 , 4 ) );   // "23"
console.log( "0123456789".substring( 2 ) );       // "23456789"
console.log( "0123456789".substring( 2 , "1" ) ); // "1"
console.log( "0123456789".substring( 4 , 2  ) );  // "23"
console.log( "0123456789".substring( -2 , 2  ) ); // "01"

 

slice()

slice()は、次のように定義されています。

substring()の定義>

String.prototype.slice( start, end )
  • start:
    startは、次の計算が適用されます。
    1. 非数値のとき、start = 0
    2. 0より大きいとき、start = min(start, 文字列長)
    3. 0より小さいとき、start = max(文字列長 + start, 0)
  • end:
    endは、次の計算が適用されます。
    1. undefined のとき、end = 文字列長
    2. 非数値のとき、end = 0
    3. 0より大きいとき、end = min(end, 文字列長)
    4. 0より小さいとき、end = max(文字列長 + end, 0)

切り出す文字数が max( end - start, 0) で計算されます。
そして、startから、その文字数分(コードユニット単位)だけ切り出されます。

■substring()の特徴
① マイナス値は文字列長+引数値に置き換えられる
② 第二引数を省略すると、文字列の最後まで切り出される。
③ 開始 > 終了のとき、切り出される文字数は0

実行例

console.log( "0123456789".slice( 2 , 4 ) );     // "23"
console.log( "0123456789".slice( 2 ) );         // "23456789"
console.log( "0123456789".slice( 2 , "1" ) );   // ""
console.log( "0123456789".slice( 4 , 2  ) );    // ""
console.log( "0123456789".slice( -8 , 7) );     // "23456"
console.log( "0123456789".slice( -8 , -5) );    // "234"

 

substr()

substr()はレガシー機能となっていて、現在のJavaScript仕様(ECMAScript)に含まれていません。
ただし同仕様で、ブラウザ上で動作するJavaScriptではレガシー機能を動作させるために組み込むよう指示されています。

そのため将来的に削除される可能性があるので、使用しない方がよさそうです。

解説はします。

substr()は、次のように定義されています。

substr()の定義>

String.prototype.substr( start, length )
  • start:
    startは、次の計算が適用されます。
    1. 非数値のとき、start = 0
    2. 0より小さいとき、start = max(文字列長 + start, 0)
  • length:
    lengthは、次の計算が適用されます。
    1. undefined のとき、end = 無限大
    2. 非数値のとき、end = 0
    3. end = min( max(end, 0), 文字列長 - start)
    4. end < 0 なら、end = 0
■substr()の特徴
① startがマイナスのとき、文字列長+startに置き換えられる
② lengthを省略すると、文字列の最後まで切り出される。
③ lengthがマイナスのとき、0に置き換えられる

 

コードポイントのサロゲートペア問題

文字列の切り出しは、コードユニット単位で行われます。

コードユニットについては、次の記事を読んでみてください。
【JavaScript】 文字列データの内部形式と関連メソッドについてまとめてみた

しかし文字によっては複数のコードユニットで一つの文字を構成するものがあります。
サロゲートペアと呼ばれるものですね。

サロゲートペアが含まれる文字列は、今回紹介したメソッドで正常に切り出しをおこなえません。
文字数が合わなかったり、文字化けをおこします。

文字化け例

const text = "🐈🐶🐑"; // 絵文字はサロゲートペア
console.log( text.substring( 0,1 ) ); // � ←文字化け
console.log( text.slice( 0,1 ) );     // �
console.log( text.substr( 0,1 ) );    // �

そのため、今回紹介したメソッドはサロゲートペアが含まれない文字列で使用する必要があります。

「ムリ」というときは、別の方法を考えます。

↓こんな感じ

const substring2 = (text,start,end) => 
    [...text].slice(start,end+1).join("");

[...text]で、一文字単位(コードユニット単位)で文字列が配列化されます。
次にslice()で配列から指定範囲の文字を抜き出して、join()で連結しています。

他にも良い方法があると思うので、いろいろ試してみてください。

更新日:2023/04/21

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。