Skip to content

Commit 5dcbeed

Browse files
committed
doc: 누락 번역 추가
1 parent c1b46ea commit 5dcbeed

1 file changed

Lines changed: 96 additions & 11 deletions

File tree

1-js/04-object-basics/02-object-copy/article.md

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
원시값(문자열, 숫자, 불린 값)은 '값 그대로' 저장·할당되고 복사되는 반면에 말이죠.
66

7-
예시:
7+
값을 복사할 때 내부에서 어떤 일이 일어나는지 살펴보면 이해하기 쉽습니다.
8+
9+
먼저 문자열 같은 원시값부터 살펴봅시다.
10+
11+
아래에선 `message`의 복사본을 `phrase`에 넣습니다.
812

913
```js
1014
let message = "Hello!";
@@ -92,7 +96,31 @@ alert( a == b ); // false
9296
9397
`obj1 > obj2` 같은 대소 비교나 `obj == 5` 같은 원시값과의 비교에선 객체가 원시형으로 변환됩니다. 객체가 어떻게 원시형으로 변하는지에 대해선 곧 학습할 예정인데, 이러한 비교(객체끼리의 대소 비교나 원시값과 객체를 비교하는 것)가 필요한 경우는 매우 드물긴 합니다. 대개 코딩 실수 때문에 이런 비교가 발생합니다.
9498
95-
## 객체 복사, 병합과 Object.assign
99+
````smart header="상수 객체는 수정될 수 있습니다."
100+
객체가 참조로 저장된다는 사실 때문에 생기는 중요한 부수 효과가 있습니다. `const`로 선언된 객체도 *수정할 수 있습니다*.
101+
102+
예시:
103+
104+
```js run
105+
const user = {
106+
name: "John"
107+
};
108+
109+
*!*
110+
user.name = "Pete"; // (*)
111+
*/!*
112+
113+
alert(user.name); // Pete
114+
```
115+
116+
`(*)`로 표시한 줄에서 오류가 발생할 것처럼 보일 수 있지만 그렇지 않습니다. `user`의 값은 상수이므로 항상 같은 객체를 참조해야 하지만, 그 객체의 프로퍼티는 자유롭게 변경할 수 있습니다.
117+
118+
다시 말해, `const user``user=...`처럼 `user` 전체에 새 값을 대입하려고 할 때만 오류를 일으킵니다.
119+
120+
그렇지만 객체 프로퍼티까지 상수로 만들어야 한다면 완전히 다른 방법을 써야 합니다. 이 방법은 <info:property-descriptors> 챕터에서 다룹니다.
121+
````
122+
123+
## 객체 복사, 병합과 Object.assign [#cloning-and-merging-object-assign]
96124

97125
객체가 할당된 변수를 복사하면 동일한 객체에 대한 참조 값이 하나 더 만들어진다는 걸 배웠습니다.
98126

@@ -150,7 +178,7 @@ let permissions2 = { canEdit: true };
150178
Object.assign(user, permissions1, permissions2);
151179
*/!*
152180
153-
// now user = { name: "John", canView: true, canEdit: true }
181+
// 이제 user = { name: "John", canView: true, canEdit: true }
154182
alert(user.name); // John
155183
alert(user.canView); // true
156184
alert(user.canEdit); // true
@@ -182,7 +210,9 @@ alert(clone.name); // John
182210
alert(clone.age); // 30
183211
```
184212

185-
예시를 실행하면 `user`에 있는 모든 프로퍼티가 빈 배열에 복사되고 변수에 할당됩니다.
213+
예시를 실행하면 `user`에 있는 모든 프로퍼티가 빈 객체에 복사되고, 그 객체가 반환됩니다.
214+
215+
객체를 복제하는 다른 방법도 있습니다. 예를 들어 튜토리얼 뒷부분에서 다룰 [스프레드 문법](info:rest-parameters-spread)을 사용하면 `clone = {...user}`처럼 객체를 복제할 수 있습니다.
186216

187217
## 중첩 객체 복사
188218

@@ -218,21 +248,76 @@ let clone = Object.assign({}, user);
218248
219249
alert( user.sizes === clone.sizes ); // true, 같은 객체입니다.
220250
221-
// user와 clone는 sizes를 공유합니다.
222-
user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다.
223-
alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다.
251+
// user와 clone은 sizes를 공유합니다.
252+
user.sizes.width = 60; // 한 객체에서 프로퍼티를 변경합니다.
253+
alert(clone.sizes.width); // 60, 다른 객체에서 변경 사항을 확인할 수 있습니다.
224254
```
225255

226-
이 문제를 해결하려면 `user[key]`의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복사해주는 반복문을 사용해야 합니다. 이런 방식을 '깊은 복사(deep cloning)'라고 합니다.
256+
이 문제를 해결해 `user``clone`을 진짜로 독립된 객체로 만들려면 `user[key]`의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복제하는 반복문을 사용해야 합니다. 이런 방식을 '깊은 복사(deep cloning)' 또는 '구조화 복사(structured cloning)'라고 합니다. 깊은 복사를 구현한 [structuredClone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) 메서드가 있습니다.
257+
258+
### structuredClone
259+
260+
`structuredClone(object)`을 호출하면 중첩 프로퍼티까지 모두 포함해 `object`가 복제됩니다.
261+
262+
앞선 예시에 이 메서드를 적용해 봅시다.
263+
264+
```js run
265+
let user = {
266+
name: "John",
267+
sizes: {
268+
height: 182,
269+
width: 50
270+
}
271+
};
272+
273+
*!*
274+
let clone = structuredClone(user);
275+
*/!*
276+
277+
alert( user.sizes === clone.sizes ); // false, 서로 다른 객체입니다.
278+
279+
// 이제 user와 clone은 완전히 독립적입니다.
280+
user.sizes.width = 60; // 한 객체에서 프로퍼티를 변경합니다.
281+
alert(clone.sizes.width); // 50, 다른 객체에는 영향을 주지 않습니다.
282+
```
283+
284+
`structuredClone` 메서드는 객체, 배열, 원시값 등 대부분의 자료형을 복제할 수 있습니다.
285+
286+
객체 프로퍼티가 객체 자신을 직접 또는 여러 참조를 거쳐 참조하는 순환 참조도 지원합니다.
287+
288+
예시:
289+
290+
```js run
291+
let user = {};
292+
// 순환 참조를 만들어 봅시다.
293+
// user.me는 user 자신을 참조합니다.
294+
user.me = user;
295+
296+
let clone = structuredClone(user);
297+
alert(clone.me === clone); // true
298+
```
299+
300+
보시다시피 `clone.me``user`가 아니라 `clone`을 참조합니다. 순환 참조도 올바르게 복제된 것입니다.
301+
302+
다만 `structuredClone`이 실패하는 경우도 있습니다.
303+
304+
예를 들어 객체에 함수 프로퍼티가 있으면 실패합니다.
305+
306+
```js run
307+
// 에러가 발생합니다.
308+
structuredClone({
309+
f: function() {}
310+
});
311+
```
227312

228-
깊은 복사 시 사용되는 표준 알고리즘인 [Structured cloning algorithm](https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data)을 사용하면 위 사례를 비롯한 다양한 상황에서 객체를 복제할 수 있습니다.
313+
함수 프로퍼티는 지원되지 않습니다.
229314

230-
자바스크립트 라이브러리 [lodash](https://lodash.com)의 메서드인 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)을 사용하면 이 알고리즘을 직접 구현하지 않고도 깊은 복사를 처리할 수 있으므로 참고하시기 바랍니다.
315+
이처럼 복잡한 경우를 처리하려면 여러 복제 방법을 조합하거나 직접 코드를 작성해야 할 수 있습니다. 바퀴를 다시 발명하지 않으려면 자바스크립트 라이브러리 [lodash](https://lodash.com)의 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) 같은 기존 구현을 사용할 수도 있습니다.
231316

232317
## 요약
233318

234319
객체는 참조에 의해 할당되고 복사됩니다. 변수엔 '객체' 자체가 아닌 메모리상의 주소인 '참조'가 저장됩니다. 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사됩니다.
235320

236321
그리고 복사된 참조를 이용한 모든 작업(프로퍼티 추가·삭제 등)은 동일한 객체를 대상으로 이뤄집니다.
237322

238-
객체의 '진짜 복사본'을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 `Object.assign`이나 '깊은 복사'를 가능하게 해주는 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)를 사용하면 됩니다. 이때 얕은 복사본은 중첩 객체를 처리하지 못한다는 점을 기억해 두시기 바랍니다.
323+
객체의 '진짜 복사본'(클론)을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 `Object.assign`을 사용하거나(중첩 객체는 참조로 복사됩니다), '깊은 복사' 함수인 `structuredClone` 혹은 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) 같은 기존 구현을 사용할 수 있습니다.

0 commit comments

Comments
 (0)