VIDEO LESSON

JavaScriptのcopyWithin():配列内の範囲を長さを変えずに上書きするの解説動画

再生時間 7:56動画を別のタブで開く ↗
動画の字幕・文字起こしを読む

再生中の字幕を濃い黒で表示し、一番上に追従します。字幕の行を選ぶと、その位置から再生できます。

  1. 0:00こんにちは。
  2. 0:01今回はジャバスクリプトのコピーウィズインを紹介します。
  3. 0:05これは、配列の一部分を、同じ配列の中の別の位置へコピーするメソッドです。
  4. 0:11コピー先にあった要素は上書きされますが、配列の長さは決して変わりません。
  5. 0:17新しい配列を作るのではなく、今ある配列をその場で書き換える点が大きな特徴です。
  6. 0:24たとえば、直近の計測値を四つだけ保ちたいとき、古い値をずらして空いた場所に新しい値を入れれば、
  7. 0:29同じ配列を使い続けられます。
  8. 0:34この動画では、基本の書き方から、範囲が重なる場合の動き、元の配列が変わってしまう注意点まで、
  9. 0:38順に解説します。
  10. 0:43初めて触れる方でも、実行結果を先に予測できるようになることを目指します。
  11. 0:49まず動作環境です。
  12. 0:50コピーウィズインは、二千十五年ごろから主要なブラウザーで広く使えるようになった機能で、
  13. 0:56現在のクローム、エッジ、ファイアフォックス、サファリで利用できます。
  14. 1:01ブラウザーで試すときは、空のタブを開き、開発者ツールのコンソールにコードを貼り付けるだけで実行できます。
  15. 1:08ドム操作は使わないので、手軽に結果を確かめられます。
  16. 1:12一方、ノード・ジェイエスでは、コードをファイルに保存し、ターミナルからノードコマンドで実行します。
  17. 1:19追加のライブラリーや特別な設定は不要です。
  18. 1:22古いブラウザーや組み込みの表示部品を対象にする場合は、事前に使えるかどうかを確認してください。
  19. 1:29基本の書き方を見ましょう。
  20. 1:31配列のあとにドット、コピーウィズインと書き、かっこの中に三つの引数を渡します。
  21. 1:37一つ目のターゲットは、コピー先の開始位置です。
  22. 1:41二つ目のスタートは、コピー元の開始位置、三つ目のエンドはコピー元の終了位置で、
  23. 1:46その位置の要素自体は含まれません。
  24. 1:50エンドを省略すると、配列の末尾までがコピー元になります。
  25. 1:55添字は先頭をゼロとして数えます。
  26. 1:57そして戻り値は、コピーした要素の数でも、新しい配列でもなく、変更された配列そのものです。
  27. 2:05この三つの位置関係を図で思い浮かべられるようになると、結果を予測しやすくなります。
  28. 2:11具体例で動きを確かめましょう。
  29. 2:14要素が一、二、三、四、五の配列で、コピーウィズイン、ゼロ、三と呼び出します。
  30. 2:21これは、添字三から末尾までの、四と五を、添字ゼロの位置へコピーするという意味です。
  31. 2:29結果は四、五、三、四、五となります。
  32. 2:33ポイントは、コピー元だった場所の値が消えるわけではないことです。
  33. 2:39コピー先にならなかった真ん中の三はそのまま残り、末尾の四と五も元の場所に残ります。
  34. 2:46あくまで上書きコピーなので、移動とは違う動きだと覚えてください。
  35. 2:52配列の長さは実行前と同じ五のままです。
  36. 2:56まずはこの基本パターンを、手元のコンソールで一度打ち込んで確かめてみてください。
  37. 3:04引数には負の数も使えます。
  38. 3:06負の添字は、配列の末尾から数えた位置として扱われます。
  39. 3:10たとえば長さ五の配列でマイナス二は、添字三と同じ場所を指します。
  40. 3:14画面の例では、末尾から二つ目の位置へ、先頭の二つの要素をコピーしています。
  41. 3:20また、コピーはコピー先の末尾で打ち切られます。
  42. 3:23ターゲットに配列の長さ以上の位置を指定すると、何もコピーされず、配列は変わりません。
  43. 3:29エンドがスタート以下になる場合も、コピー対象は空になります。
  44. 3:34ただし通常のコードでは、まずゼロ以上の整数で範囲を指定する方が、読み手に意図が伝わりやすくなります。
  45. 3:41ここからは実践例です。
  46. 3:43直近四回の計測値を保つ関数を作ります。
  47. 3:47処理の中心は二行だけです。
  48. 3:49まずコピーウィズイン、ゼロ、一で、二番目以降の値を先頭へコピーして左へずらします。
  49. 3:56次に、末尾の枠へ新しい計測値を代入します。
  50. 4:00たとえば十八、二十、十九、二十一という配列に二十二を加えると、二十、十九、
  51. 4:05二十一、二十二に更新されます。
  52. 4:09関数の前半では、配列かどうか、要素数が四かどうか、新しい値が有限の数かどうかを先に検査しています。
  53. 4:18変更前にまとめて検証することで、エラーが起きたときに配列が中途半端に書き換わる事態を防げます。
  54. 4:27先ほどの例では、コピー元とコピー先の範囲が重なっています。
  55. 4:31コピー元は添字一から三、コピー先は添字ゼロから二です。
  56. 4:35途中で上書きが起きるのに、なぜコピー元の並びが壊れないのでしょうか。
  57. 4:40コピーウィズインは、重なりを考慮して正しくコピーするよう定められているため、
  58. 4:44結果は二十、十九、二十一と正しい順序で写ります。
  59. 4:49コピー直後の配列は、二十、十九、二十一、二十一です。
  60. 4:53末尾の二十一はコピー先にならなかったので残っています。
  61. 4:57だからこそ、そのあと末尾へ新しい値を代入する手順が欠かせません。
  62. 5:01この代入を忘れると、古い値が重複したままになってしまいます。
  63. 5:06よくある勘違いが、戻り値の扱いです。
  64. 5:08コピーウィズインの戻り値を別の変数に入れても、それは元の配列と同じ実体を指しています。
  65. 5:15片方を変更すれば、もう片方からも同じ変更が見えてしまいます。
  66. 5:19変更前の状態を残しておきたい場合は、操作の前に配列を複製してください。
  67. 5:25画面の例では、スプレッド構文で複製した側だけにコピーウィズインを適用しているので、
  68. 5:30元の配列は十、二十、三十、四十のまま保たれています。
  69. 5:35ただし、この複製は浅いコピーです。
  70. 5:37要素がオブジェクトの場合、そのオブジェクト自体は複製されません。
  71. 5:42次のセクションで、その点を詳しく見ます。
  72. 5:45要素がオブジェクトの場合の注意点です。
  73. 5:48スコアが一と二の、二つのオブジェクトを持つ配列で、先頭の要素を二番目へコピーします。
  74. 5:55このときコピーされるのは、オブジェクトの中身の複製ではなく、同じオブジェクトへの参照です。
  75. 6:01そのため、二番目のスコアを九に書き換えると、一番目のスコアも九に見えます。
  76. 6:07両方の添字が、まったく同じオブジェクトを指しているからです。
  77. 6:12独立した編集用データを作りたい場面では、コピーウィズインをそのまま使うことはできません。
  78. 6:19用途に応じて、オブジェクト自体を複製する処理を別に用意してください。
  79. 6:24失敗例と制約も押さえておきましょう。
  80. 6:26要素を書き換えられない配列に対してコピーウィズインを使うと、タイプエラーが発生する場合があります。
  81. 6:34また、特殊な読み書き処理を持つ配列では、コピーの途中で例外が起きる可能性もあります。
  82. 6:40その場合、すでに書き換わった部分が自動で元に戻る保証はありません。
  83. 6:45さらに、空きスロットのある疎な配列では、その空き自体もコピー先へ伝わります。
  84. 6:51安全に使うコツは、普段自分で作った、空きのない通常の配列を対象にすることです。
  85. 6:56この処理は同期的で、アウェイトやプロミスの待機は不要です。
  86. 7:01例外はその場で発生するので、必要に応じてトライ・キャッチで囲んでください。
  87. 7:06最後に活用場面とまとめです。
  88. 7:09コピーウィズインが向いているのは、直近の計測値、一定数の処理時間、固定幅の作業データなど、
  89. 7:14要素数を保ったまま範囲をずらしたい場面です。
  90. 7:19逆に、一覧の途中に要素を挿入したり削除したりしたい場合は、求める操作が違うので、
  91. 7:23別のメソッドを検討してください。
  92. 7:28導入するときは、更新処理を関数の形にまとめ、元の配列が変わることを呼び出し側にも分かるようにしておくと安全です。
  93. 7:36複数の場所で同じ配列を共有している場合は、上書きの影響範囲を先に確認しましょう。
  94. 7:43合言葉は、長さを変えずに、その場でずらすならコピーウィズインです。
  95. 7:48範囲の指定に慣れるまでは、小さな配列で結果を予測してから実行する練習がおすすめです。
  96. 7:54お疲れさまでした。
日本語字幕をダウンロード(WebVTT)

この動画で学べること

Array.prototype.copyWithin()で同じ配列内の要素を上書きコピーする方法を解説。引数・戻り値、ブラウザーとNode.jsでの実行手順、範囲の重なりや参照共有の注意点を学べます。

解説記事・サンプルコードを読む:JavaScriptのcopyWithin():配列内の範囲を長さを変えずに上書きする →