スプレッド構文の使い方【JavaScript】
スプレッド構文
スプレーや霧吹きは、高圧の空気などを用いて、液体を霧状に噴出する装置です。
この機構を最初に思いついた人は天才だなあ、と思います。
そういうものはたくさんありますが、自分の身近にあるものは尚更そう感じます。
そんなスプレーのように、配列やオブジェクトの値を拡散させることが可能なのが、スプレッド構文です。
スプレッド演算子、という呼び名も使われているようですが、MDNでは スプレッド構文となっているので、ここではその呼称で統一します。
1. 基本的な使い方 2. Arrayリテラルでの使用例 3. Objectリテラルでの使用例 4. 注意点 5. 参考
1. 基本的な使い方
以下の例では、関数sumの引数に、構文である...
をつけて配列numsを渡しています。このように記述することで、配列の値を、sum関数のx、y、zに割り当てることができます。
const sum = (x, y, z) => x + y + z const nums = [1, 5, 15] console.log( sum(...nums) ) // 21
また、関数の引数をスプレッド構文にすれば、関数に渡される引数を配列として扱うことができます。
const test = (...nums) => nums[1] console.log(test(1, 5, 15)) // 5
2. Arrayリテラルでの使用例
配列のコピー
スプレッド構文によるコピーはシャローコピーとなります。
const ary1 = [1, 2, 3] // 配列のコピー const ary2 = ary1 // 参照渡し const ary3 = [...ary1] // シャローコピー // コピー検証 console.log(ary1 === ary2) // true console.log(ary1 === ary3) // false // 要素を追加した新しい配列を作成 const ary4 = ['hello', ...ary1, 7] // ['hello', 1, 2, 3, 7]
シャローコピーなので、ネストになっている配列とオブジェクトには注意が必要です。
(対象がネストになっていると、ディープコピーではすべての階層について実体をコピーするのに対し、シャローコピーでは最初の1階層のみ実体がコピーされる)
const baseArray = [1, [2, 3], [4, 5]] let copyArray = [...baseArray] copyArray[0] = 'aaa' copyArray[1][0] = 'bbb' console.log(baseArray, copyArray) // [ 1, [ 'bbb', 3 ], [ 4, 5 ] ] [ 'aaa', [ 'bbb', 3 ], [ 4, 5 ] ]
配列のマージ
concat()
を使わず、簡潔に書けるようになりました。
const ary1 = ["a", 0, "b"] const ary2 = [1, "hello", 99] const ary3 = [...ary1, ...ary2] // ["a", 0, "b", 1, "hello", 99]
3. Objectリテラルでの使用例
コピーとマージの方法、結果は配列と同じです。
オブジェクトのコピー
const obj1 = {name: "tanaka", age: 20} // オブジェクトのコピー const obj2 = obj1 // 参照渡し const obj3 = {...obj1} // シャローコピー // コピー検証 console.log(obj1 === obj2) // true console.log(obj1 === obj3) // false // 要素を追加した新しいオブジェクトを作成 const obj4 = {...obj1, hobby: "guiter"} // { name: "tanaka", age: 20, hobby: "guiter" }
配列と同じく、ネストされているオブジェクトには注意。
const baseObject = { name: { firstname: "Taro", familyname: "Tanaka" }, age: 20 } let copyObject = {...baseObject} copyObject.name.firstname = "Jiro" copyObject.age = 35 console.log(baseObject, copyObject) // {age: 20, name: { familyname: "Tanaka", firstname: "Jiro" } } // {age: 35, name: { familyname: "Tanaka", firstname: "Jiro" } }
オブジェクトのマージ
const human = {name: "tanaka", age: 20} const subinfo = {hobby: "guiter", job: "enginner"} const tanaka = {...human, ...subinfo} // {name: "tanaka", age: 20, hobby: "guiter", job: "enginner"}
4. 注意点
オブジェクト内に配列は展開できるが、配列にオブジェクトは展開できない
以下のようにオブジェクトを配列内に展開しようとするとエラーになります。
const obj = {name: "tanaka", age: 20} const ary = [1, ...obj, 2] // TypeError: obj is not iterable
ただし、配列をオブジェクトに展開することは可能です。
const ary = ["Takana play guiter.", "Human data"] const obj = {name: "tanaka", age: 20, ...ary} // {0: "Takana play guiter.", 1: "Human data", name: "tanaka", age: 20}
null, undefined
nullやundefinedをスプレッド構文で扱おうとすると、配列はエラーになるが、オブジェクトの場合はエラーになりません。
// 配列 [...null] // Uncaught TypeError: object null is not iterable [...undefined] // Uncaught TypeError: undefined is not iterable // オブジェクト {...null} // {} {...undefined} // {}
IE未対応
言わずもがな。