分割代入とスプレッド構文、シャローコピー
TypeScript,JavaScript 初学者が関数の分割代入とスプレッド構文、シャローコピートについて勉強したのでメモを残す。
配列のプロパティ名のショートハンド
- まずは下記の例を読んでみる
const object1 = { bar: 10, baz: 20, foo: 30 };
const object2 = { foo };
console.log(object2); // { foo: 30 }
-
object1
のキーfoo
をobject2
に代入することで、object2
がキーfoo
,値30
のオブジェクトになる
分割代入
- 続いて分割代入を見てみる
// 分割代入
const [num1, num2] = [10, 20];
console.log(num1, num2); // 10 20
// オブジェクトの代入
const object = { name: "Yasushi", age: 27 };
const { name, age } = object;
console.log(name, age); // Yasushi 27
スプレッド構文
- 配列の中身を展開する構文で、スプレッド構文というものがある。
// 配列のスプレッド構文
> const array01 = ['A', 'B', 'C']
> array01
[ 'A', 'B', 'C' ]
> const array02 = [...array01, 'D', 'E', 'F']
> array02
[ 'A', 'B', 'C', 'D', 'E', 'F' ]
// オブジェクトのスプレッド構文
> const object01 = { a: 1, b: 2, c: 3, d: 4 }
> const object02 = { ...object1, e: 5, f: 6, g: 7 }
> object01
{ a: 1, b: 2, c: 3, d: 4 }
> object02
{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }
- 配列やオブジェクトの名前の前に
...
をつけることで中身が展開される。
マージとコピー
-
オブジェクト型の値は参照渡しのため、コピーしてもアドレスが異なるため
true
にはならない。下のコード参照。> const sample = { a: 1, b: 2, c: 3 } > const sampleCopy = Object.assign({}, sample); > // sample { a: 1, b: 2, c: 3 } > // sampleCopy { a: 1, b: 2, c: 3 } > sample==sampleCopy false
-
Object.assign()
は第1引数がコピー先オブジェクトなのだが、割り当てた後に中身が書き変わってしまうため使うには注意が必要。コツとして第1引数にスプレッド構文
を使うことでコピー元が書き変わることを防ぐことができる。
-
シャローコピーには注意
-
オブジェクトをコピーする際に、プロパティ値がオブジェクトだった時にオブジェクトへの参照がコピーされてしまう。そのためコピー先でそのプロパティ値を変えてしまうと、参照元のオブジェクト、つまりコピー元が書き変わってしまう。
> const sample = { isSample1: true, isSample2: false, objectProperty: { isSample1: true, isSample2: false, } } > const sample1 = sample // 浅いプロパティを書き換える > const sample2 = {...sample, isSample1: false, isSample2: true} // 深いプロパティ(オブジェクト)を書き換える > sample2.objectProperty.isSample1 = false > sample2.objectProperty.isSample2 = true > sample2 { isSample1: false, isSample2: true, objectProperty: { isSample1: false, isSample2: true } } > sample1 { isSample1: true, isSample2: false, objectProperty: { isSample1: false, isSample2: true } // シャローコピーを考慮できていないバグ(書き変わってしまった) }
- 回避策として、
一旦JSONで文字列に展開してパース
する方法がある。
> const sample2 = JSON.perse(JSON.stringify(sample1)); > sample2.objectProperty.isSmaple1 = false > sample2.objectProperty.isSmaple2 = true > sample1 { isSample1: false, isSample2: true, objectProperty: { isSample1: true, isSample2: false } // 参照していないので書き変わらない }
- 回避策として、
参考
何か指摘等ございましたら、コメントでお願いいたします。