73363


下記のサイトで読んだコード内に記された。

### 分からない事

`this.products.push(...Array(amount).fill(product));` この部分がよくわかりません。

配列にオブジェクトを代入しているのは何となく見てわかるのですが、 `0: Product {name: "bread", price: 1} 1:
Product {name: "bread", price: 1}`このようなオブジェクトが配列に格納されています。

### 知りたい事

この `...Array()`に数値を引数で取ると`fill()`に渡した引数のコピーをその数だけしてくれるのでしょうか？  
`...`の付いたもの初めて見るので困惑しています。

[JavaScriptとオブジェクト指向プログラミング](https://postd.cc/javascript-and-object-oriented-
programming/)

[code]

    class Product {
      constructor(name, price) {
        this.name = name;
        this.price = price;
      }
    }
     
    class Book extends Product {
      constructor(name, price, author) {
        super(name, price);
        this.author = author;
      }
    }
     
    class Basket {
      constructor() {
        this.products = [];
      }
     
      addProduct(amount, product) {
        this.products.push(...Array(amount).fill(product));
        console.log(this.products)
      }
     
      calcTotal() {
        return this.products
          .map(product => product.price)
          .reduce((a, b) => a + b, 0);
      }
     
      printShoppingInfo() {
        console.log('one has to pay in total: ' + this.calcTotal());
      }
    }
     
    const bread = new Product('bread', 1);
    const water = new Product('water', 0.25);
    const faust = new Book('faust', 12.5, 'Goethe');
     
    const basket = new Basket();
    basket.addProduct(2, bread);
    basket.addProduct(3, water);
    basket.addProduct(1, faust);
    basket.printShoppingInfo();
    
[/code]


CC BY-SA 4.0
2021-01-17T05:29:53.177
73361
2021-01-17T08:28:55.093
22565
question
javascript
JavaScriptの...Array(amount).fill(product)の動作がよく分からない。


> `this.products.push(...Array(amount).fill(product));`

について、`Array(amount)`, `fill(product)`, `...`と、３つに分けて説明させていただきます。

### 1\. `Array(amount)`

> `Array()` コンストラクターは `Array` オブジェクトを生成するために使用します。
> [Ref](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/Array)

表示されているスクリプトから、`amount`は整数値であることがわかります。これと上記の説明から、`Array(amount)`を実行すると、`amount`の数の要素を持った1次元配列が作成されます。ただし、この場合、各要素は初期化されていないため、`JSON.stringify(Array(amount))`を見ると、`[null,null,,,]`となります。

### 2\. `fill(product)`

> `fill()` メソッドは、開始インデックス（デフォルトは `0`）から終了インデックス（デフォルトは
> `array.length`）までのすべての要素を、静的な値に変更した配列を返します。
> [Ref](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/fill)

表示されているスクリプトから、例えば`const bread = new Product('bread',
1)`を実行すると、`bread`の値が、`fill(product)`の`product`に渡されます。例えば、`Array(3).fill("sample")`を実行すると、`[
'sample', 'sample', 'sample' ]`のような配列が返されます。

### 3\. `...`

> `Array`の左側にある`...`は、スプレッド構文です。スプレッド構文 (`...`) を使うと、配列式や文字列などの反復可能オブジェクトを、0
> 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値のペア
> (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。
> [Ref](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

上記の1,2の説明から、`Array(amount).fill(product)`は、`amount`の要素数を持つ`product`の値で初期化された配列であることがわかりました。そのため、例えば、`amount`,
`product`がそれぞれ`3`, `sample`とすると、`Array(amount).fill(product)`は、`[ 'sample',
'sample', 'sample' ]`です。これを配列`this.products = []`へプッシュすると、`this.products = [[
'sample', 'sample', 'sample' ]]`のように2次元配列になります。

ここで、`...`を使用すると、`...Array(amount).fill(product)`は、`sample sample
sample`となり、これを配列`this.products = []`へプッシュすると、`this.products = [ 'sample',
'sample', 'sample' ]`のように1次元配列になります。この場合、`this.products.push('sample',
'sample', 'sample')`のようにプッシュする配列が展開されてプッシュされます。

追記として、表示されているスクリプトでは、3つの値`bread`, `water`, `faust`が初期化された`const basket = new
Basket()`のメソッド`addProduct`へ渡されて、それぞれの値が順にプッシュされます。このとき、`...`を使用しない場合、`basket.addProduct(2,
bread)`, `basket.addProduct(3, water)`, `basket.addProduct(1,
faust)`のそれぞれが配列としてプッシュされるため、結果は2次元配列になります。そこで、`...`を使用することで、1次元配列として出力されます。

ちなみに、`this.products.push(...Array(amount).fill(product))`は、`this.products =
this.products.concat(Array(amount).fill(product))`や`this.products =
[...this.products, ...Array(amount).fill(product)]`などと同じ動作です。

### References:

  * [Array() コンストラクター](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/Array)
  * [fill()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/fill)
  * [スプレッド構文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)


CC BY-SA 4.0
2021-01-17T08:28:55.093
73363
2021-01-17T08:28:55.093
19460
73361
answer