関数・メソッド

【JavaScript】配列(Arrayオブジェクト)のwith()メソッドの使い方

更新日:2023/06/23

ECMAScript2023で配列(Arrayオブジェクト)にwith()が追加されました。
JavaScriptにはwith構文がありますが、このメソッドは同じような意味なのでしょうか。
ということで、使い方等をお伝えします。

 

with()メソッドとは

配列(Arrayオブジェクト)のwith()は、配列をコピーするメソッドです。
ついでに、引数で指定したインデックスの値を変更してくれます。
※指定できるインデックスは、一つだけです。

JavaScriptにはwith構文が存在しますが、Arrayオブジェクトのwith()メソッドとは意味的に全く異なります。

with構文については、次のページを読んでみてください。非推奨だけど…
【JavaScript】 今更だけど非推奨なwith構文を理解してみる

むしろ、with()メソッドの名前つけが意味不明かもしれない。

 

with()メソッドの構文

with()メソッドは、次のように定義されています。

Array.prototype.with ( index, value )
  • index:

    値を変更するインデックスの番号です。
    値がマイナスの場合、配列の長さ(lengthプロパティ)に加算した値をインデックスとして使用します。

    例:
    indexが-1なら、配列の最後。
    indexが-2なら、配列の最後から2番目。

    ただし、次の範囲で指定する必要があります。

    lengthプロパティ * -1 <= index <= lengthプロパティ -1

    つまり、元となる配列の範囲外に要素を追加することはできません。

  • value:

    追加する値です。

 

使用例

with()の使用例です。

const ary = [0,1,2,3,4];

console.log( ary.with( 2,10 ) );  // 結果: [0, 1, 10, 3, 4]
console.log( ary.with( -2,10 ) ); // 結果: [0, 1, 2, 10, 4]

console.log( ary ); // 結果: [0, 1, 2, 3, 4]

最後のログ出力は、元となる配列が変更されていない(非破壊)ことを確認しています。

 

代替例

コピー後に一か所だけ値を変更するケースは、あまりないような気がしますね。
次のようなコードでも、同じ結果を得られます。

const copyAry = Array.from( ary );
copyAry[2] = 10;
console.log( copyAry ); // 結果: [0, 1, 10, 3, 4]

Array.from()はmap()のようにコールバック関数を指定できます。
そこで、次のように書き換えできます。

console.log( Array.from( ary , (value,index) => index === 2 ? 10 : value ) );
 // 結果: [0, 1, 10, 3, 4]

めんどくさいコードになった...

with()が使えるなら、素直に使った方がよさそうです。

 

インデックスが欠けている時の動作

with()は配列をコピーするメソッドですが、実際は完全なコピーではありません。

配列は仕様上、一部または全てのインデックスが存在していなくても問題ありません。
このような配列をコピーした場合、完全なコピーならインデックスが欠けたままコピーされるべきです。

ですが実際には、値をundefinedとしてインデックスが追加されます。

const ary = [0,1,,,4];
ary[7] = 7;

console.log( ary );  // 結果: [0, 1, 空 × 2, 4, 空 × 2, 7]
console.log( ary.with( 2,10 ) ); // 結果: [0, 1, 10, undefined, 4, undefined, undefined, 7]

結果はChromeのコンソールに出力されたものです。
Chromeではインデックスが存在しない場合、"空" と表示されます。

一方のundefinedはインデックスが存在していて、値がundefinedであるという意味です。

完全なコピーでwith()と同じことを行うなら、Object.assign()でコピー後に値を変更します。

const copyAry = Object.assign( [] ,ary);
copyAry[2] = 10;

console.log( copyAry ); // 結果: [0, 1, 10, なし, 4, 空 × 2, 7]

結果の "なし" は "空" と同じ意味です。

Object.assign( )の第一引数に、{ } ではなくて [] を指定するのがポイントです。

 

ArrayLikeなオブジェクト

with()はArrayLikeなオブジェクトをコピー元として処理できます。

ArrayLikeなオブジェクトとは、lengthプロパティを持つオブジェクトです。
■参考記事:【JavaScript】 アレイライク・配列風・配列のようなオブジェクトとは

元となるのはオブジェクトですが、結果は配列になります。

const aryLike = {length:6};

console.log( Array.prototype.with.call( aryLike , 3 , 100 ) );
  // 結果: [undefined, undefined, undefined, 100, undefined, undefined]

 

FireFoxは未実装

2023年6月の時点で、FireFoxはwith()が実装されていないようです。
ブラウザで使用するのは、もう少し待つ必要がありますね。

更新日:2023/06/23

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

スポンサーリンク

記事の内容について

null

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

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

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

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

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

 

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