読者です 読者をやめる 読者になる 読者になる

LS&TK's SE Life Log

SE備忘録

lodashのclone(isDeep)とcloneDeepの検証

lodashには_.cloneと_.cloneDeepというオブジェクト複製のコマンドがあります。 cloneの方は基本的にShallowCloneととでも言うのか、参照の複製を行います。 一方cloneDeepは参照の複製ではなく、同じ値のオブジェクトを再生成して複製します。ここまでなら解りやすいですね。

ですがcloneにはisDeepというパラメータにtrueを渡すことでdeepにcloneできるというのです。

じゃぁclone(isDeep)とcloneDeepの違いはなんなんだ?ということで簡単に調べてみました。

var users = [
  { 'user': 'john', 'age': 35 },
  { 'user': 'fred', 'age': 29 }
];

var cloneShallow = _.clone(users);
var cloneIsDeep = _.clone(users, true);
var cloneDeep = _.cloneDeep(users);

console.log(users[0] == cloneShallow[0]); // true
console.log(users[0] == cloneIsDeep[0]);  // false
console.log(users[0] == cloneDeep[0]);    // false

JavaScriptの等価演算子でオブジェクトを比較した場合、オブジェクトの参照先が同じかどうかで判断されます。 よって、通常のcloneの場合usersとcloneShallowは同じ参照を持っている為trueになりますね。 一方clone(isDeep)とcloneDeepは新しいオブジェクトを生成するのでfalseになります。

あれ?同じ?

ちなみに勿論ですが各objの値自体は同じです。

console.dir(users);
console.dir(cloneShallow);
console.dir(cloneDeeper);
console.dir(cloneDeepest);

// 上記の結果は全て以下の通り
// [[object Object] {
//   age: 35,
//   user: "john"
// }, [object Object] {
//   age: 29,
//   user: "fred"
// }]

結局ソース見てみたんですが、同じでした。 cloneもcloneDeepもbaseCloneというprivateメソッドを利用していて、それに対してparamのisDeepを引数として渡すか固定で渡すかの違い。

baseClone(obj, isDeep); //clone
baseClone(obj, true); //cloneDeep