객체복사
- 객체와 원시타입의 근본적인 차이중 하나는 객체는 참조에 의해 저장되고 복사된다.
- 원시값은 값드래도 저장,할당되고 복사된다.
기본형(원시타입)
- 복제방식: 값이담긴 주소값을 바로 복제
- 불변성의 여부: 불변성을 띔
참조형(객체)
- 복제방식: 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
- 불변성의 여부: 불변성을 띄지 않음
let sayHello = "Hello!";
let copy = sayHello;
console.log(sayHello) //"Hello!"
console.log(copy) // "Hello!"
- 예시를 실행하면 두 개의 독립된 변수에 각각 문자열 "Hello!"가 저장됨
- 객체의 동작 방식은 객체가 저장되어 있는 메모리 주소인 객체에 대한 참조 값이 저장됨
let user = {
name: "John"
};
- 객체는 메모리 내 어딘가에 저장되고, 변수 user엔 객체를 참조 할 수 있는 값이 저장된다. 따라서 객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않는다.
let user = { name: "John" };
let admin = user; // 참조값을 복사함
console.log(user) //{name: 'John'}
console.log(admin) //{name: 'John'}
- 변수는 두 개이지만 각 변수엔 동일 객체에 대한 참조 값이 저장
let user = { name: 'John' };
let admin = user;
admin.name = 'hi'; // 'admin' 참조 값에 의해 변경됨
admin.age = 30 //변수 'admin' 에 age:30 값을 추가
console.log(user.name , user.age); // 'hi , 30'이 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함
console.log(user) // {name: "hi" , age: 30}
- 객체를 서랍장에 비유하면 변수는 서랍장을 열 수 있는 열쇠이다. 서랍장은 하나, 서랍장을 열 수 있는 열쇠는 두개인데 그중 하나(admin)를 사용해 서랍장을 열어 정돈한후, 또 다른 열쇠 (user)로 서랍장을 열면 정돈된 내용을 볼 수 있다.
서랍장은 하나다 = 저장된 값은 하나
열수있는 열쇠 = 변수명 (키는 여러개가 될수있음 하지만 저장된 값은하나임)
참조에 의한 비교
- 객체 비교시 동등 연산자 == 와 일치 연산자 ===는 동일하게 동작한다. 비교시 두객체가 동인할 객체인 경우에 true 반환
let a = {name: "marry"};
let b = a; // 참조에 의한 복사
console.log( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
console.log( a === b ); // true
console.log(a) //{name: 'marry'}
console.log(b) //{name: 'marry'}
- 참조되지 않은 다른 두객체
let a = {name: "marry"};
let b = {name: "marry"}; // 독립된 두 객체
console.log( a == b ); // false
console.log( a === b ); // false
console.log(a) //{name: 'marry'}
console.log(b) //{name: 'marry'}
- 객체끼리의 대소 비교나 원시값과 객체를 비교하는 것이 필요한경우는 드물다. 코딩 실수 때문에 발생한다(데이터의 값을 확인 잘하자.)
객체복사
- 객체가 할당된 변수를 복사하면 객체에 대한 참조 값이 하나더 만들어 진다(서랍은 하나이고, 서랍을 열수 있는 열쇠는 여러개이다.)
- 객체 복제가 필요한 상황이라면 새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 원시수준까지 프로퍼티를 복사하면 된다.
let user = {
name: "John",
age: 30
};
let clone = {}; // 새로운 빈 객체
// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
for (let key in user) {
clone[key] = user[key];
}
console.log(clone) //{name: 'John', age: 30}
// 이제 clone은 완전히 독립적인 복제본이 되었습니다.
clone.name = "Pete"; // clone의 데이터를 변경합니다.
clone.age = 26
clone.isMarried = false
console.log( user.name ); // 기존 객체에는 여전히 John이 있습니다.
console.log( clone) // {name: 'Pete', age: 26, isMarried: false}
- for in을 통해 clone 변수를 user객체와 같은 값을 참조하지 않고 독립적인 객체가 됨
object.assign
- Object.assign를 사용하는 방법도 있습니다.
- dest = 변경하기 위한 객체
- src1 ... srcN은 복사하고자 하는 객체
Object.assign(dest, [src1, src2, src3...])
예시
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);
console.log(user) // { name: "John", canView: true, canEdit: true }
혼자 해보기
let object = {
name: 'jjangu',
age: 5,
hasMom: true
}
let friend1 = {friend1: "yuri"}
let friend2 = {friend2:"mangu"}
Object.assign(object, friend1, friend2)
console.log(object) // {name: 'jjangu', age: 5, hasMom: true, friend1: 'yuri', friend2: 'mangu'}
object.assing을 사용하면 반복문없이도 간단하게 객체를 복사 할 수 있다.
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
clone.name = "jjangu"
console.log(clone) // {name:"jjangu", age: 30}
console.log(clone === user) //false
- user에 있는 모든 프로퍼티가 빈배열에 복사되고 변수에 할당된다 user와 clone은 같은 값을 참조하는 객체가 아닌 서로 다른 값을 참조하는 "완전히 다른 객체"가 된다.
중첩 객체 복사
- 객체의 프로퍼티가 다른객체에 대한 참조 값일 경우
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
console.log( user.sizes.height ); // 182
console.log( user.sizes.width ); // 50
console.log( user.sizes ) // { height:182, width: 50}
clone.sizes = user.sizes로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없습니다. user.sizes는 객체이기 때문에 참조 값이 복사되기 때문입니다. clone.sizes = user.sizes로 프로퍼티를 복사하면 clone과 user는 같은 sizes를 공유하게 됩니다.
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, 같은 객체입니다.
// user와 clone는 sizes를 공유합니다.
user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다.
console.log(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다.
- user와 clone변수는 같은 값을 참조하고 있다. object.assing 메서드로 user변수를 clone 변수에 옮겼지만 같은 객체 값이 원시데이터가 아닌 객체이므로 참조 값이 분리되지 않는다.
- user변수와 clone변수를 각각 다른 객체로 분리하려면 user[key]의 각 값을 검사하면서 그값이 객체인 경우 객체의 구조도 복사해 주는 반복문을 사용해야 한다. 이런 방식을 깊은 복사(deep cloning) 라고한다.
참고 : 자바스크립트 라이브러리 lodash의 메서드인 _.cloneDeep(obj)를 사용하면 깊은 복사를 처리할 수 있다.
요약
- 객체는 참조에 의해 할당되고 복사된다. 변수엔 객체 자체가 아닌 메모리상의 주소인 참조가 저장된다 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사된다.
- 복사된 참조를 이용한 모든 작업은 동일한 객체를 대상을 이뤄진다.
- 객체의 진자 복사본을 만들려면 얕은 복사(shallow copy) 를 가능하게 해주는 Object.assing 메서드나 깊은 복사를 가능하게 해주는_.cloneDeep(obj)를 사용하면된다. 이때 얕은 복사는 중첩 객체(객체안의 객체)를 처리하지 못한다.얕은 복사를 해결하기 위해 또다른 방법은 for in 반복문을 통해 각 프로퍼티가 객체인지 판단하면서 객체구조일 경우 각 구조의 원시타입까지 가서 복제를 해주는 반복문을 사용해야한다 깊은 복사(Deep Cloning)
출처 및 참조
https://ko.javascript.info/object-copy
참조에 의한 객체 복사
ko.javascript.info
'Javascript' 카테고리의 다른 글
이벤트 루프 (0) | 2023.07.19 |
---|---|
new Date() 객체 (0) | 2023.04.06 |
자바스크립트 화살표 함수 (0) | 2023.04.05 |
자바스크립트 문자열 메서드 정리 (0) | 2023.03.20 |
자바스크립트 배열 메서드정리 (0) | 2023.03.19 |
객체복사
- 객체와 원시타입의 근본적인 차이중 하나는 객체는 참조에 의해 저장되고 복사된다.
- 원시값은 값드래도 저장,할당되고 복사된다.
기본형(원시타입)
- 복제방식: 값이담긴 주소값을 바로 복제
- 불변성의 여부: 불변성을 띔
참조형(객체)
- 복제방식: 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
- 불변성의 여부: 불변성을 띄지 않음
let sayHello = "Hello!";
let copy = sayHello;
console.log(sayHello) //"Hello!"
console.log(copy) // "Hello!"
- 예시를 실행하면 두 개의 독립된 변수에 각각 문자열 "Hello!"가 저장됨
- 객체의 동작 방식은 객체가 저장되어 있는 메모리 주소인 객체에 대한 참조 값이 저장됨
let user = {
name: "John"
};
- 객체는 메모리 내 어딘가에 저장되고, 변수 user엔 객체를 참조 할 수 있는 값이 저장된다. 따라서 객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않는다.
let user = { name: "John" };
let admin = user; // 참조값을 복사함
console.log(user) //{name: 'John'}
console.log(admin) //{name: 'John'}
- 변수는 두 개이지만 각 변수엔 동일 객체에 대한 참조 값이 저장
let user = { name: 'John' };
let admin = user;
admin.name = 'hi'; // 'admin' 참조 값에 의해 변경됨
admin.age = 30 //변수 'admin' 에 age:30 값을 추가
console.log(user.name , user.age); // 'hi , 30'이 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함
console.log(user) // {name: "hi" , age: 30}
- 객체를 서랍장에 비유하면 변수는 서랍장을 열 수 있는 열쇠이다. 서랍장은 하나, 서랍장을 열 수 있는 열쇠는 두개인데 그중 하나(admin)를 사용해 서랍장을 열어 정돈한후, 또 다른 열쇠 (user)로 서랍장을 열면 정돈된 내용을 볼 수 있다.
서랍장은 하나다 = 저장된 값은 하나
열수있는 열쇠 = 변수명 (키는 여러개가 될수있음 하지만 저장된 값은하나임)
참조에 의한 비교
- 객체 비교시 동등 연산자 == 와 일치 연산자 ===는 동일하게 동작한다. 비교시 두객체가 동인할 객체인 경우에 true 반환
let a = {name: "marry"};
let b = a; // 참조에 의한 복사
console.log( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
console.log( a === b ); // true
console.log(a) //{name: 'marry'}
console.log(b) //{name: 'marry'}
- 참조되지 않은 다른 두객체
let a = {name: "marry"};
let b = {name: "marry"}; // 독립된 두 객체
console.log( a == b ); // false
console.log( a === b ); // false
console.log(a) //{name: 'marry'}
console.log(b) //{name: 'marry'}
- 객체끼리의 대소 비교나 원시값과 객체를 비교하는 것이 필요한경우는 드물다. 코딩 실수 때문에 발생한다(데이터의 값을 확인 잘하자.)
객체복사
- 객체가 할당된 변수를 복사하면 객체에 대한 참조 값이 하나더 만들어 진다(서랍은 하나이고, 서랍을 열수 있는 열쇠는 여러개이다.)
- 객체 복제가 필요한 상황이라면 새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 원시수준까지 프로퍼티를 복사하면 된다.
let user = {
name: "John",
age: 30
};
let clone = {}; // 새로운 빈 객체
// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
for (let key in user) {
clone[key] = user[key];
}
console.log(clone) //{name: 'John', age: 30}
// 이제 clone은 완전히 독립적인 복제본이 되었습니다.
clone.name = "Pete"; // clone의 데이터를 변경합니다.
clone.age = 26
clone.isMarried = false
console.log( user.name ); // 기존 객체에는 여전히 John이 있습니다.
console.log( clone) // {name: 'Pete', age: 26, isMarried: false}
- for in을 통해 clone 변수를 user객체와 같은 값을 참조하지 않고 독립적인 객체가 됨
object.assign
- Object.assign를 사용하는 방법도 있습니다.
- dest = 변경하기 위한 객체
- src1 ... srcN은 복사하고자 하는 객체
Object.assign(dest, [src1, src2, src3...])
예시
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);
console.log(user) // { name: "John", canView: true, canEdit: true }
혼자 해보기
let object = {
name: 'jjangu',
age: 5,
hasMom: true
}
let friend1 = {friend1: "yuri"}
let friend2 = {friend2:"mangu"}
Object.assign(object, friend1, friend2)
console.log(object) // {name: 'jjangu', age: 5, hasMom: true, friend1: 'yuri', friend2: 'mangu'}
object.assing을 사용하면 반복문없이도 간단하게 객체를 복사 할 수 있다.
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
clone.name = "jjangu"
console.log(clone) // {name:"jjangu", age: 30}
console.log(clone === user) //false
- user에 있는 모든 프로퍼티가 빈배열에 복사되고 변수에 할당된다 user와 clone은 같은 값을 참조하는 객체가 아닌 서로 다른 값을 참조하는 "완전히 다른 객체"가 된다.
중첩 객체 복사
- 객체의 프로퍼티가 다른객체에 대한 참조 값일 경우
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
console.log( user.sizes.height ); // 182
console.log( user.sizes.width ); // 50
console.log( user.sizes ) // { height:182, width: 50}
clone.sizes = user.sizes로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없습니다. user.sizes는 객체이기 때문에 참조 값이 복사되기 때문입니다. clone.sizes = user.sizes로 프로퍼티를 복사하면 clone과 user는 같은 sizes를 공유하게 됩니다.
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, 같은 객체입니다.
// user와 clone는 sizes를 공유합니다.
user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다.
console.log(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다.
- user와 clone변수는 같은 값을 참조하고 있다. object.assing 메서드로 user변수를 clone 변수에 옮겼지만 같은 객체 값이 원시데이터가 아닌 객체이므로 참조 값이 분리되지 않는다.
- user변수와 clone변수를 각각 다른 객체로 분리하려면 user[key]의 각 값을 검사하면서 그값이 객체인 경우 객체의 구조도 복사해 주는 반복문을 사용해야 한다. 이런 방식을 깊은 복사(deep cloning) 라고한다.
참고 : 자바스크립트 라이브러리 lodash의 메서드인 _.cloneDeep(obj)를 사용하면 깊은 복사를 처리할 수 있다.
요약
- 객체는 참조에 의해 할당되고 복사된다. 변수엔 객체 자체가 아닌 메모리상의 주소인 참조가 저장된다 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사된다.
- 복사된 참조를 이용한 모든 작업은 동일한 객체를 대상을 이뤄진다.
- 객체의 진자 복사본을 만들려면 얕은 복사(shallow copy) 를 가능하게 해주는 Object.assing 메서드나 깊은 복사를 가능하게 해주는_.cloneDeep(obj)를 사용하면된다. 이때 얕은 복사는 중첩 객체(객체안의 객체)를 처리하지 못한다.얕은 복사를 해결하기 위해 또다른 방법은 for in 반복문을 통해 각 프로퍼티가 객체인지 판단하면서 객체구조일 경우 각 구조의 원시타입까지 가서 복제를 해주는 반복문을 사용해야한다 깊은 복사(Deep Cloning)
출처 및 참조
https://ko.javascript.info/object-copy
참조에 의한 객체 복사
ko.javascript.info
'Javascript' 카테고리의 다른 글
이벤트 루프 (0) | 2023.07.19 |
---|---|
new Date() 객체 (0) | 2023.04.06 |
자바스크립트 화살표 함수 (0) | 2023.04.05 |
자바스크립트 문자열 메서드 정리 (0) | 2023.03.20 |
자바스크립트 배열 메서드정리 (0) | 2023.03.19 |