フロントエンド面接問題-オブジェクトコピー方法の概要
3322 ワード
1.オブジェクトコピー方法
1.1
1.2
1.3
1.4解体賦課
解構賦値法を用いて浅いコピーを行った.
2.手書きオブジェクトの深いコピー方法
2.1 ES 5オブジェクトの深いコピーを実現
2.2 ES 6オブジェクトの深いコピーを実現
オブジェクトの深いコピーは可能ですが、ループ参照が発生するとデッドループになります.そのため、
1.1
JSON.parse
およびJSON.stringify
の方法JSON.stringify
およびJSON.parse
法を用いて深コピーを行ったが,関数およびundefined
をコピーすることはできず,オブジェクトプロトタイプチェーン上の属性および方法をコピーすることもできなかった.var obj = {
a: 1,
b: 2,
c: {
d: 4,
// JSON ,undefined
e: undefined,
// null JSON null => "f": null
f: null
},
f: function () { console.log('function'); }
};
var newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj.c.d); // 4
console.log(newObj.e); // undefined
console.log(newObj.f); // undefined
1.2
for-in
サイクルfor-in
サイクルを用いて浅いコピーが行われ、基本タイプのデータのみがコピーされ、参照タイプのデータに対してはポインタのみがコピーされる.var obj = {
a: 1,
b: {
c: 3
}
};
var newObj = {};
for (var key in obj) {
newObj[key] = obj[key];
}
newObj.b.c = 4;
console.log(obj.b.c); // 4
console.log(newObj.b.c); // 4
1.3
Object.assign
方法Object.assign
法を用いて、ソースオブジェクトの列挙可能および固有の属性をコピーする浅いコピーが行われる.var obj = {
a: 1,
b: {
c: 3
}
};
var newObj = {};
Object.assign(newObj, obj);
newObj.b.c = 4;
console.log(obj.b.c); // 4
console.log(newObj.b.c); // 4
1.4解体賦課
解構賦値法を用いて浅いコピーを行った.
var obj = {
a: 1,
b: {
c: 1
}
}
var newObj = {...obj}
newObj.b.c = 2
console.log(obj.b.c) // 2
console.log(newObj.b.c) // 2
2.手書きオブジェクトの深いコピー方法
2.1 ES 5オブジェクトの深いコピーを実現
function deepClone (origin, target) {
var _tar = target || {}
for (var key in origin) {
if (origin.hasOwnProperty(key)) {
if (typeof origin[key] === 'object' && origin[key] !== null) {
_tar[key] = Object.prototype.toString.call(origin[key]) === '[object Array]' ? [] : {};
deepClone(origin[key], _tar[key]);
} else _tar[key] = origin[key];
}
}
return _tar
}
var obj = {
a: 1,
b: 2,
c: {
d: 4,
e: 5
},
f: function () { console.log('function'); }
};
var newObj = {};
deepClone(obj, newObj);
console.log(newObj.c.d); // 4
console.log(newObj.f); // undefined
2.2 ES 6オブジェクトの深いコピーを実現
function deepClone (origin) {
if (origin == undefined || typeof origin !== 'object') return origin;
if (origin instanceof Date) return new Date(origin);
if (origin instanceof RegExp) return new RegExp(origin);
const target = new origin.constructor();
for (let key in origin) {
if (origin.hasOwnProperty(key)) {
target[key] = deepClone(origin[key]);
}
}
return target;
}
オブジェクトの深いコピーは可能ですが、ループ参照が発生するとデッドループになります.そのため、
WeakMap
によってコピーされたオブジェクトを保存し、デッドサイクルを防止する必要がある.function deepClone (origin, hashMap = new WeakMap()) {
if (origin == undefined || typeof origin !== 'object') return origin;
if (origin instanceof Date) return new Date(origin);
if (origin instanceof RegExp) return new RegExp(origin);
const hashVal = hashMap.get(origin);
if (hashVal) return hashVal;
const target = new origin.constructor();
hashMap.set(origin, target);
for (let key in origin) {
if (origin.hasOwnProperty(key)) {
target[key] = deepClone(origin[key]);
}
}
return target;
}