5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptAdvent Calendar 2018

Day 11

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

Last updated at Posted at 2018-12-10

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

突然ですが

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

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. ほかに気付いたこと? 何でも

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

5
2
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?