Edited at

JavaScript: f( array ) よりも f( [...array] ) がいいとき?

単純なことなんですが、最近うっかり踏みそうになったプチ地雷からのクイズ?です。


突然ですが

何が表示されるでしょうか?

const array2Gen = xs =>

function*(){ yield* xs; }();

const a = [0,1,2];
const g =array2Gen( a );

for(let i of a.keys() ){
a[i] = undefined;
console.log(g.next().value);
};

配列をジェネレータにして、順番に配列の要素の値を変更しながらジェネレータを呼んで表示させるということです。

こんなこと普通はしないでしょうけど。

答は:

undefined

undefined
undefined

です。

const で配列を宣言しても、配列の要素は変更できるのでしたね。ある意味、当然の結果です。

でも場合によっては、ジェネレータにした時点で中味が固定されて、もう変ってほしくないと思うんじゃないでしょうか?


0 1 2 が返ってきてほしいなあ...


うけとった配列をコピーして使う

これはどうでしょう。何が表示されるでしょうか?

const array2Gen = xs =>

function*(){
const ys = [...xs];
yield* ys;
}();

const a = [0,1,2];
const g =array2Gen( a );

for(let i of a.keys() ){
a[i] = undefined;
console.log(g.next().value);
};

受け取った配列 xs を[...xs]で浅いコピーをしてからジェネレータにしています。

これで xs が変更されても大丈夫なはずです。

が、実行してみると...

undefined

1
2

あれ?一回目だけ変更されてる。なぜでしょう?

説明できます?

ともかく、このやりかたでは不十分です。別のやりかたを考えましょう。


コピーしてから渡す

今度はどうでしょう。何が表示されるでしょうか?

const array2Gen = xs =>

function*(){ yield* xs; }();

const a = [0,1,2];
const g = array2Gen( [...a] );

for(let i of a.keys() ){
a[i] = undefined;
console.log(g.next().value);
};

今度は const g = array2Gen( [...a] );で浅いコピーをしてから関数に渡しています。

結果は?:

0

1
2

やったー!やっとできたー


まとめ


  1. 何でできたんだろう? 説明できる?

  2. いつもコピーしたほうがいい? どんなときにコピーするべき?

  3. 配列だけ? 他に気をつけたほうがいいモノは?

  4. 浅いコピーで大丈夫? どうやって見分ける?

  5. やった方がいいことは? 逆にやらない方がいいことは?

  6. ほかに気付いたこと? 何でも

...というようなクイズ? なんですが、何かお役に立つ内容でしたでしょうか?