細かい仕様の違いはあるかもしれないが、大体以下の感じで理解している。
スプレッド構文
Array に関しては Ruby でいう配列の展開(*
)とほぼ同じかな。
スプレッド構文を使うと、関数呼び出しでは 0 個以上の引数として、Array リテラルでは 0 個以上の要素として、Object リテラルでは 0 個以上の key-value のペアとして、Array や String などの iterable オブジェクトをその場で展開します。
function sum(x, y, z) { return x + y + z; } const numbers = [1, 2, 3]; console.log(sum(...numbers)); // expected output: 6 console.log(sum.apply(null, numbers)); // expected output: 6
関数呼び出しとかと一緒に使わないで単独で ...numbers
とかってやると syntax error になる。(これは Ruby も同じ)
Object に関してはまだ proposal っぽいけど、JS の方はそのまま Object のまま展開されるのに対して、 Ruby のハッシュ展開は以下のように配列に変換されるのでちょっと仕様が違いそう。
$ irb > hash = { x: 1, y: 2, z: 3 } => {:x=>1, :y=>2, :z=>3} > a, b, c = *hash => [[:x, 1], [:y, 2], [:z, 3]] > a => [:x, 1] > b => [:y, 2] > c => [:z, 3]
レスト構文(分割代入)
レスト構文はスプレッド構文と全く同じ見た目をしていますが、Array や Object の分割代入に使われます。こちらはスプレッド構文とは逆の働きといえます: スプレッド構文が要素を展開するのに対して、レスト構文は複数の要素を集約して 1 つのオブジェクトにします。
Array
Ruby で可変長引数を扱うための splat パラメータ(*
)とほぼ同じかな。
function sum(...theArgs) { return theArgs.reduce((previous, current) => { return previous + current; }); } console.log(sum(1, 2, 3)); // expected output: 6 console.log(sum(1, 2, 3, 4)); // expected output: 10
Object
Ruby のダブル splat パラメータ(**
)の object でやり取りする版かな。(Ruby のはキーワード引数リストをハッシュとして受け取る)
今はまだ Proposal のようだ。
Rest/Spread Properties for ECMAScript 提案 (ステージ 3) は、分割代入に rest 構文を追加します。残余プロパティは、分割パターンによってすでに取り出されていない、残りの列挙可能なプロパティのキーを収集します。
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40} a; // 10 b; // 20 rest; // { c: 30, d: 40 }
参考
Rest parameters - JavaScript | MDN
GitHub - tc39/proposal-object-rest-spread: Rest/Spread Properties for ECMAScript