확산 구문을 사용하는 ES6의 전체 복사
배열이 아닌 객체로 작동하는 Redux 프로젝트에 대한 깊은 복사 맵 방법을 만들려고합니다. Redux에서 각 상태는 이전 상태에서 아무것도 변경해서는 안된다고 읽었습니다.
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
output[key] = callback.call(this, {...object[key]});
return output;
}, {});
}
효과가있다:
return mapCopy(state, e => {
if (e.id === action.id) {
e.title = 'new item';
}
return e;
})
그러나 내부 항목을 딥 복사하지 않으므로 다음과 같이 조정해야합니다.
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
let newObject = {...object[key]};
newObject.style = {...newObject.style};
newObject.data = {...newObject.data};
output[key] = callback.call(this, newObject);
return output;
}, {});
}
어떤 객체가 전달되는지 알아야하기 때문에 덜 우아합니다. ES6에서 스프레드 구문을 사용하여 객체를 딥 복사하는 방법이 있습니까?
ES6에는 이러한 기능이 내장되어 있지 않습니다. 하고 싶은 일에 따라 몇 가지 옵션이 있다고 생각합니다.
정말 깊은 복사를 원하는 경우 :
- 도서관을 이용하세요. 예를 들어 lodash에는
cloneDeep
메서드가 있습니다. - 자신 만의 복제 기능을 구현하십시오.
특정 문제에 대한 대체 솔루션 (딥 카피 없음)
그러나 몇 가지를 기꺼이 바꾸고 싶다면 약간의 작업을 절약 할 수 있습니다. 나는 당신이 당신의 기능에 대한 모든 호출 사이트를 제어한다고 가정하고 있습니다.
전달 된 모든 콜백
mapCopy
이 기존 객체를 변경하는 대신 새 객체를 반환 하도록 지정 합니다. 예를 들면 :mapCopy(state, e => { if (e.id === action.id) { return Object.assign({}, e, { title: 'new item' }); } else { return e; } });
이를 사용
Object.assign
하여 새 개체를 만들고 해당 새 개체에e
대한 속성 을 설정 한 다음 새 개체에 새 제목을 설정합니다. 즉, 기존 개체를 변경하지 않고 필요할 때만 새 개체를 만듭니다.mapCopy
이제 정말 간단 할 수 있습니다.export const mapCopy = (object, callback) => { return Object.keys(object).reduce(function (output, key) { output[key] = callback.call(this, object[key]); return output; }, {}); }
기본적 mapCopy
으로 발신자가 올바른 일을하도록 신뢰하는 것입니다. 이것이 내가 이것이 모든 통화 사이트를 제어한다고 가정 한 이유입니다.
대신 딥 카피에 이것을 사용하십시오.
var newObject = JSON.parse(JSON.stringify(oldObject))
var oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
var newObject = JSON.parse(JSON.stringify(oldObject));
newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);
MDN에서
참고 : 스프레드 구문은 배열을 복사하는 동안 효과적으로 한 수준 깊이가됩니다. 따라서 다음 예제와 같이 다차원 배열을 복사하는 데 적합하지 않을 수 있습니다 (Object.assign () 및 스프레드 구문과 동일 함).
개인적 으로 다단계 개체 / 어레이 복제를 위해 Lodash의 cloneDeep 함수를 사용하는 것이 좋습니다 .
다음은 작동하는 예입니다.
const arr1 = [{ 'a': 1 }];
const arr2 = [...arr1];
const arr3 = _.clone(arr1);
const arr4 = arr1.slice();
const arr5 = _.cloneDeep(arr1);
const arr6 = [...{...arr1}]; // a bit ugly syntax but it is working!
// first level
console.log(arr1 === arr2); // false
console.log(arr1 === arr3); // false
console.log(arr1 === arr4); // false
console.log(arr1 === arr5); // false
console.log(arr1 === arr6); // false
// second level
console.log(arr1[0] === arr2[0]); // true
console.log(arr1[0] === arr3[0]); // true
console.log(arr1[0] === arr4[0]); // true
console.log(arr1[0] === arr5[0]); // false
console.log(arr1[0] === arr6[0]); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
나는 이것을 자주 사용합니다 :
function deepCopy(obj) {
if(typeof obj !== 'object' || obj === null) {
return obj;
}
if(obj instanceof Date) {
return new Date(obj.getTime());
}
if(obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = deepCopy(item);
return arr;
}, []);
}
if(obj instanceof Object) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepCopy(obj[key]);
return newObj;
}, {})
}
}
function deepclone(obj) {
let newObj = {};
if (typeof obj === 'object') {
for (let key in obj) {
let property = obj[key],
type = typeof property;
switch (type) {
case 'object':
if( Object.prototype.toString.call( property ) === '[object Array]' ) {
newObj[key] = [];
for (let item of property) {
newObj[key].push(this.deepclone(item))
}
} else {
newObj[key] = deepclone(property);
}
break;
default:
newObj[key] = property;
break;
}
}
return newObj
} else {
return obj;
}
}
// use: clone( <thing to copy> ) returns <new copy>
// untested use at own risk
function clone(o, m){
// return non object values
if('object' !==typeof o) return o
// m: a map of old refs to new object refs to stop recursion
if('object' !==typeof m || null ===m) m =new WeakMap()
var n =m.get(o)
if('undefined' !==typeof n) return n
// shallow/leaf clone object
var c =Object.getPrototypeOf(o).constructor
// TODO: specialize copies for expected built in types i.e. Date etc
switch(c) {
// shouldn't be copied, keep reference
case Boolean:
case Error:
case Function:
case Number:
case Promise:
case String:
case Symbol:
case WeakMap:
case WeakSet:
n =o
break;
// array like/collection objects
case Array:
m.set(o, n =o.slice(0))
// recursive copy for child objects
n.forEach(function(v,i){
if('object' ===typeof v) n[i] =clone(v, m)
});
break;
case ArrayBuffer:
m.set(o, n =o.slice(0))
break;
case DataView:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.byteLength))
break;
case Map:
case Set:
m.set(o, n =new (c)(clone(Array.from(o.entries()), m)))
break;
case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
case Int16Array:
case Uint16Array:
case Int32Array:
case Uint32Array:
case Float32Array:
case Float64Array:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.length))
break;
// use built in copy constructor
case Date:
case RegExp:
m.set(o, n =new (c)(o))
break;
// fallback generic object copy
default:
m.set(o, n =Object.assign(new (c)(), o))
// recursive copy for child objects
for(c in n) if('object' ===typeof n[c]) n[c] =clone(n[c], m)
}
return n
}
나는 지난날이 답변에 착수하여 재귀 링크를 포함 할 수있는 복잡한 구조를 딥 복사하는 방법을 찾으려고 노력했습니다. 이전에 제안 된 내용에 만족하지 않았기 때문에이 바퀴를 직접 구현했습니다. 그리고 그것은 아주 잘 작동합니다. 누군가에게 도움이되기를 바랍니다.
사용 예 :
OriginalStruct.deep_copy = deep_copy; // attach the function as a method
TheClone = OriginalStruct.deep_copy();
사용 방법에 대한 실제 예제 는 https://github.com/latitov/JS_DeepCopy 를 참조하십시오. 또한 deep_print ()도 있습니다.
빨리 필요한 경우 deep_copy () 함수의 소스가 바로 여기에 있습니다.
function deep_copy() {
'use strict'; // required for undef test of 'this' below
// Copyright (c) 2019, Leonid Titov, Mentions Highly Appreciated.
var id_cnt = 1;
var all_old_objects = {};
var all_new_objects = {};
var root_obj = this;
if (root_obj === undefined) {
console.log(`deep_copy() error: wrong call context`);
return;
}
var new_obj = copy_obj(root_obj);
for (var id in all_old_objects) {
delete all_old_objects[id].__temp_id;
}
return new_obj;
//
function copy_obj(o) {
var new_obj = {};
if (o.__temp_id === undefined) {
o.__temp_id = id_cnt;
all_old_objects[id_cnt] = o;
all_new_objects[id_cnt] = new_obj;
id_cnt ++;
for (var prop in o) {
if (o[prop] instanceof Array) {
new_obj[prop] = copy_array(o[prop]);
}
else if (o[prop] instanceof Object) {
new_obj[prop] = copy_obj(o[prop]);
}
else if (prop === '__temp_id') {
continue;
}
else {
new_obj[prop] = o[prop];
}
}
}
else {
new_obj = all_new_objects[o.__temp_id];
}
return new_obj;
}
function copy_array(a) {
var new_array = [];
if (a.__temp_id === undefined) {
a.__temp_id = id_cnt;
all_old_objects[id_cnt] = a;
all_new_objects[id_cnt] = new_array;
id_cnt ++;
a.forEach((v,i) => {
if (v instanceof Array) {
new_array[i] = copy_array(v);
}
else if (v instanceof Object) {
new_array[i] = copy_object(v);
}
else {
new_array[i] = v;
}
});
}
else {
new_array = all_new_objects[a.__temp_id];
}
return new_array;
}
}
건배@!
const cloneData = (dataArray) => {
newData= []
dataArray.forEach((value) => {
newData.push({...value})
})
return newData
}
- a = [{이름 : "siva"}, {이름 : "siva1"}];
- b = myCopy (a)
- b === a // 거짓`
참고 URL : https://stackoverflow.com/questions/38416020/deep-copy-in-es6-using-the-spread-syntax
'developer tip' 카테고리의 다른 글
X 분마다 cronjob을 실행하는 방법은 무엇입니까? (0) | 2020.10.16 |
---|---|
AngularJS 1.5+ 구성 요소는 감시자를 지원하지 않습니다. 해결 방법은 무엇입니까? (0) | 2020.10.16 |
Python에서 객체 목록 검색 (0) | 2020.10.15 |
후행 슬래시가없는 django URL은 리디렉션되지 않습니다. (0) | 2020.10.15 |
변수의 값을 다른 값으로 복사 (0) | 2020.10.15 |