LoginSignup
1
0

More than 3 years have passed since last update.

JavaScript Primer「オブジェクト」#深いコピー(deep copy)の例題を理解する

Last updated at Posted at 2021-01-07

JavaScript Primer 第一部:基本文法「オブジェクト」の#オブジェクトの複製深いコピー(deep copy)が何をしているのか理解できませんでした。学習の過程においては、そんなにこだわるところではなかったかもしれませんが、理解できなくて気持ち悪かったので整理。

以下、JS Primerの解説を引用しておきます。

逆にプロパティの値までも再帰的に複製してコピーすることを、深いコピー(deep copy)と呼びます。 deep copyは、再帰的にshallow copyすることで実現できます。 次のコードでは、deepCloneをshallowCloneを使うことで実現しています。

このように、JavaScriptのビルトインメソッドは浅い(shallow)実装のみを提供し、深い(deep)実装は提供していないことが多いです。 言語としては最低限の機能を提供し、より複雑な機能はユーザー側で実装するという形式を取るためです。

// 引数の`obj`を浅く複製したオブジェクトを返す
const shallowClone = (obj) => { //(5)
    return Object.assign({}, obj);
};
// (3)
// 引数の`obj`を深く複製したオブジェクトを返す
function deepClone(obj) {
    //(4)
    const newObj = shallowClone(obj); // => {level: 1, nest: {level: 2}}
    // プロパティがオブジェクト型であるなら、再帰的に複製する
    // (6)
    Object.keys(newObj) //引数内のオブジェクトのキー(左側)を一つずつ抜き出してくる(forEachに似てる?)
        .filter(k => typeof newObj[k] === "object") // (7)
        .forEach(k => newObj[k] = deepClone(newObj[k])); // (8)
    return newObj;
}
//(1)
const obj = { 
    level: 1,
    nest: {
        level: 2
    }
};
//(2)
const cloneObj = deepClone(obj);
// (9)`nest`オブジェクトも再帰的に複製されている
console.log(cloneObj.nest === obj.nest); // => false

以下、実際のプログラムの動きとは違うと思いますが、入門者の自分が理解しやすいように流れを整理してみます。

  1. obj変数にオブジェクトが代入される
  2. cloneObj変数に、1のobj変数を引数に渡すdeepClone関数が代入すると宣言される。
  3. 2.で呼ばれたdeepClone関数を実行していく。
  4. shallowClone関数式を呼び、引数にobjを渡し、newObjに代入する。(関数式はその変数名で参照できる)
  5. shallowClone関数式の無名関数を実行する。Object.assignメソッドで第一引数のからオブジェクト{}にobjを合体させ(クローンする)、それを返す。
  6. Object.keysで仮引数内のオブジェクト(newObj)のキーを1つ1つ展開する。
  7. Array.filterで引数に与えられた関数でnewObjのキーを一つ一つ検査し、該当するプロパティだけで新しい配列を作り、返す。(→if文みたい!)検査内容は、そのキーのデータ型が"object"かどうか(「は?」と思った入門者は下図1参照)。つまり{level: 2}だけの配列ができる。
  8. それに対してforEachを仕掛けて、一つ一つのプロパティに引数内の無名関数を実行する。deepClone関数(自分)を実行し(自分を呼ぶから再帰的と呼ぶ)、newObjオブジェクトのキーkのプロパティにその結果を代入する。x-yの処理が{level: 2}に対して再度行われる。newObjを返す。
  9. オリジナルのobjのキーnestとクローンしたcloneObjのキーnestを比較し、falseとなるので、複製されたオブジェクトとわかる。

図1:
スクリーンショット 2021-01-07 15.13.47.png

以上です。
てか、コピーと謳うのであれば、プログラムのコードでもCloneではなく、Copyとしてくれればよかったのに、と思うのは私だけでしょうか。

1
0
1

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
1
0