DBILITY

javascript deep copy 본문

front-end & ui/javascript

javascript deep copy

DBILITY 2021. 10. 25. 18:19
반응형

primitive type인 string, number (en-US), bigint (en-US), boolean, undefined, symbol, null는 값 복사( call stack에 실제 값도 저장 )가 이루어 진다.

function,array,object는 참조값이라 참조값( call stack에 heap의 주소값 저장 )이 복사된다. 자세한 것은 v8엔진 메모리구조 검색.

... ( spread연산자 )로 copy를 할 경우 1차원 배열에서는 deep copy ( 새로운 힙 메모리 할당 )가 이루어지나 2차원 이상에서는 shallow copy ( 메모리 참조 )가 된다.
1차원 배열의 경우에도 배열의 원소가 object일 경우 shallow copy가 된다.
그냥 vuejs에선 lodash의 cloneDeep을 사용하자.
vue import시 사용하고자 하는 기능만도 가능하다. ( import _cloneDeep from "lodash/cloneDeep" )
JSON.parse(JSON.stringify(array_in_object)) 또는 재귀 호출로 일일이 복사하던가. 나의 무식함을 욕하지 말자. 항상 쓰는 것도 기억하지 못한다.

/*
* 원시타입 string,number
* */
let primitive_string = "마녀배달부키키는퇴직했나보다";
let primitive_number = 7;

/*
* 참조타입 array,object
* */

let array_in_string = ['오징어게임', '승리호', '마녀배달부키키는퇴직했나보다'];
let array_in_object = [
    {
        id: 0,
        title: '오징어게임',
        price: 10000,
        count: 0
    },
    {
        id: 1,
        title: '승리호',
        price: 8000,
        count: 0,
    },
    {
        id: 2,
        title: '마녀배달부키키는퇴직했나보다',
        price: 9000,
        count: 0
    }
];

const deepCopy = function (obj) {
    if (obj == null || typeof obj !== 'object') {
        return obj;
    }
    let result = Array.isArray(obj) ? [] : {};
    for (let key of Object.keys(obj)) {
        result[key]= deepCopy(obj[key]);
    }
    return result;
}

let a = primitive_number;
let b = a;

console.log('a = %s , b = %s', a, b);
console.log('a === b %s', a === b);

b = 0;
console.log('a = %s , b = %s', a, b);
console.log('a === b %s', a === b);


let a1 = primitive_string;
let b1 = a1;

console.log('a1 = %s , b1 = %s', a1, b1);
console.log('a1 === b1 %s', a1 === b1);

b1 = "승리호";
console.log('a1 = %s , b1 = %s', a1, b1);
console.log('a1 === b1 %s', a1 === b1);

let a2 = [...array_in_string];
let b2 = a2;
let c2 = [...array_in_string];
console.log('a2 = %o , b2 = %o', a2, b2);
console.log('a2 === b2 %s', a2 === b2);

a2[0] = "오징어게임2";
console.log('a2 = %o , b2 = %o', a2, b2);
console.log('a2 === b2 %s', a2 === b2);
console.log('a2 = %o , c2 = %o', a2, c2);
console.log('a2 === c2 %s', a2 === c2);

let org_data = JSON.parse(JSON.stringify(array_in_object));
let i = array_in_object;
let j = i;
j[0].count = 1;
console.log('i = %o , j = %o', i, j);
console.log('i === j %s', i === j);
let k = [...org_data];
console.log('i = %o , k = %o', i, k);
console.log('i === k %s', i === k);

let deepClone = deepCopy(org_data);
k[0].count = 1;
console.log('k = %o , deepClone = %o', k, deepClone);
console.log('k === deepClone %s', k === deepClone);

결과는 그림 1과 같다.

그림1
es6spreadcopy.html
0.00MB

ES6방식으로 deepCopy용 helper를 제작한다면 다음과 같다.import해 사용해 보니 잘된다.

export default {
    deepCopy(obj) {
        if (obj == null || typeof obj !== 'object') {
            return obj;
        }
        let result = Array.isArray(obj) ? [] : {};

        for (let key of Object.keys(obj)) {
            result[key] = this.deepCopy(obj[key]);
        }
        return result;
    }
};

 

반응형
Comments