From 317cc753089e4865bcc15b4dab5ae5aeea368e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Thu, 14 May 2026 21:17:53 +0900 Subject: [PATCH 01/21] =?UTF-8?q?docs:=20js/04-object-basics/01-object=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 61 ---------------------- 1 file changed, 61 deletions(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 9ea60fc048..63412c01fa 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -5,11 +5,7 @@ 그런데 객체형은 원시형과 달리 다양한 데이터를 담을 수 있습니다. 키로 구분된 데이터 집합이나 복잡한 개체(entity)를 저장할 수 있죠. 객체는 자바스크립트 거의 모든 면에 녹아있는 개념이므로 자바스크립트를 잘 다루려면 객체를 잘 이해하고 있어야 합니다. -<<<<<<< HEAD 객체는 중괄호 `{…}`를 이용해 만들 수 있습니다. 중괄호 안에는 '키(key): 값(value)' 쌍으로 구성된 *프로퍼티(property)* 를 여러 개 넣을 수 있는데, `키`엔 문자형, `값`엔 모든 자료형이 허용됩니다. 프로퍼티 키는 '프로퍼티 이름' 이라고도 부릅니다. -======= -An object can be created with curly braces `{…}` with an optional list of *properties*. A property is a "key: value" pair, where `key` is a string (also called a "property name"), and `value` can be anything. ->>>>>>> upstream/master 서랍장을 상상하면 객체를 이해하기 쉽습니다. 서랍장 안 파일은 프로퍼티, 파일 각각에 붙어있는 이름표는 객체의 키라고 생각하시면 됩니다. 복잡한 서랍장 안에서 이름표를 보고 원하는 파일을 쉽게 찾을 수 있듯이, 객체에선 키를 이용해 프로퍼티를 쉽게 찾을 수 있습니다. 추가나 삭제도 마찬가지입니다. @@ -24,11 +20,7 @@ let user = {}; // '객체 리터럴' 문법 ![](object-user-empty.svg) -<<<<<<< HEAD 중괄호 `{...}`를 이용해 객체를 선언하는 것을 *객체 리터럴(object literal)* 이라고 부릅니다. 객체를 선언할 땐 주로 이 방법을 사용합니다. -======= -Usually, the curly braces `{...}` are used. That declaration is called an *object literal*. ->>>>>>> upstream/master ## 리터럴과 프로퍼티 @@ -52,11 +44,7 @@ let user = { // 객체 ![user object](object-user.svg) -<<<<<<< HEAD 서랍장에 파일을 추가하고 뺄 수 있듯이 개발자는 프로퍼티를 추가, 삭제할 수 있습니다. -======= -We can add, remove and read files from it at any time. ->>>>>>> upstream/master 점 표기법(dot notation)을 이용하면 프로퍼티 값을 읽는 것도 가능합니다. @@ -74,11 +62,7 @@ user.isAdmin = true; ![user object 2](object-user-isadmin.svg) -<<<<<<< HEAD `delete` 연산자를 사용하면 프로퍼티를 삭제할 수 있습니다. -======= -To remove a property, we can use the `delete` operator: ->>>>>>> upstream/master ```js delete user.age; @@ -108,7 +92,6 @@ let user = { ``` 이런 쉼표를 'trailing(길게 늘어지는)' 혹은 'hanging(매달리는)' 쉼표라고 부릅니다. 이렇게 끝에 쉼표를 붙이면 모든 프로퍼티가 유사한 형태를 보이기 때문에 프로퍼티를 추가, 삭제, 이동하는 게 쉬워집니다. -<<<<<<< HEAD ````smart header="상수 객체는 수정될 수 있습니다." 주의하세요. `const`로 선언된 객체는 수정될 수 있습니다. @@ -134,9 +117,6 @@ alert(user.name); // Pete ```` ## 대괄호 표기법 -======= -## Square brackets ->>>>>>> upstream/master 여러 단어를 조합해 프로퍼티 키를 만든 경우엔, 점 표기법을 사용해 프로퍼티 값을 읽을 수 없습니다. @@ -245,21 +225,13 @@ let bag = { }; ``` -<<<<<<< HEAD 대괄호 표기법은 프로퍼티 이름과 값의 제약을 없애주기 때문에 점 표기법보다 훨씬 강력합니다. 그런데 작성하기 번거롭다는 단점이 있습니다. -======= -Square brackets are much more powerful than dot notation. They allow any property names and variables. But they are also more cumbersome to write. ->>>>>>> upstream/master 이런 이유로 프로퍼티 이름이 확정된 상황이고, 단순한 이름이라면 처음엔 점 표기법을 사용하다가 뭔가 복잡한 상황이 발생했을 때 대괄호 표기법으로 바꾸는 경우가 많습니다. ## 단축 프로퍼티 -<<<<<<< HEAD 실무에선 프로퍼티 값을 기존 변수에서 받아와 사용하는 경우가 종종 있습니다. -======= -In real code, we often use existing variables as values for property names. ->>>>>>> upstream/master 예시: @@ -304,11 +276,7 @@ let user = { ## 프로퍼티 이름의 제약사항 -<<<<<<< HEAD 아시다시피 변수 이름(키)엔 'for', 'let', 'return' 같은 예약어를 사용하면 안됩니다. -======= -As we already know, a variable cannot have a name equal to one of the language-reserved words like "for", "let", "return" etc. ->>>>>>> upstream/master 그런데 객체 프로퍼티엔 이런 제약이 없습니다. @@ -381,11 +349,7 @@ alert( "blabla" in user ); // user.blabla는 존재하지 않기 때문에 false `in` 왼쪽엔 반드시 *프로퍼티 이름*이 와야 합니다. 프로퍼티 이름은 보통 따옴표로 감싼 문자열입니다. -<<<<<<< HEAD 따옴표를 생략하면 아래 예시와 같이 엉뚱한 변수가 조사 대상이 됩니다. -======= -If we omit quotes, that means a variable should contain the actual name to be tested. For instance: ->>>>>>> upstream/master ```js run let user = { age: 30 }; @@ -415,11 +379,7 @@ alert( "test" in obj ); // `in`을 사용하면 프로퍼티 유무를 제대로 `undefined`는 변수는 정의되어 있으나 값이 할당되지 않은 경우에 쓰기 때문에 프로퍼티 값이 `undefined`인 경우는 흔치 않습니다. 값을 '알 수 없거나(unknown)' 값이 '비어 있다는(empty)' 것을 나타낼 때는 주로 `null`을 사용합니다. 위 예시에서 `in` 연산자는 자리에 어울리지 않는 초대손님처럼 보이네요. -<<<<<<< HEAD ## 'for..in' 반복문 -======= -## The "for..in" loop [#forin] ->>>>>>> upstream/master `for..in` 반복문을 사용하면 객체의 모든 키를 순회할 수 있습니다. `for..in`은 앞서 학습했던 `for(;;)` 반복문과는 완전히 다릅니다. @@ -476,11 +436,7 @@ for (let code in codes) { */!* ``` -<<<<<<< HEAD 현재 개발 중인 애플리케이션의 주 사용자가 독일인이라고 가정해 봅시다. 나라 번호를 선택하는 화면에서 `49`가 맨 앞에 오도록 하는 게 좋을 겁니다. -======= -The object may be used to suggest a list of options to the user. If we're making a site mainly for a German audience then we probably want `49` to be the first. ->>>>>>> upstream/master 그런데 코드를 실행해 보면 예상과는 전혀 다른 결과가 출력됩니다. @@ -492,7 +448,6 @@ The object may be used to suggest a list of options to the user. If we're making ````smart header="정수 프로퍼티? 그게 뭔가요?" '정수 프로퍼티'라는 용어는 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미합니다. -<<<<<<< HEAD 문자열 "49"는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티입니다. 하지만 '+49'와 '1.2'는 정수 프로퍼티가 아닙니다. ```js run @@ -500,16 +455,6 @@ The object may be used to suggest a list of options to the user. If we're making alert( String(Math.trunc(Number("49"))) ); // '49'가 출력됩니다. 기존에 입력한 값과 같으므로 정수 프로퍼티입니다. alert( String(Math.trunc(Number("+49"))) ); // '49'가 출력됩니다. 기존에 입력한 값(+49)과 다르므로 정수 프로퍼티가 아닙니다. alert( String(Math.trunc(Number("1.2"))) ); // '1'이 출력됩니다. 기존에 입력한 값(1.2)과 다르므로 정수 프로퍼티가 아닙니다. -======= -So, `"49"` is an integer property name, because when it's transformed to an integer number and back, it's still the same. But `"+49"` and `"1.2"` are not: - -```js run -// Number(...) explicitly converts to a number -// Math.trunc is a built-in function that removes the decimal part -alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property -alert( String(Math.trunc(Number("+49"))) ); // "49", not same "+49" ⇒ not integer property -alert( String(Math.trunc(Number("1.2"))) ); // "1", not same "1.2" ⇒ not integer property ->>>>>>> upstream/master ``` ```` @@ -558,15 +503,9 @@ for (let code in codes) { - 프로퍼티 키는 문자열이나 심볼이어야 합니다. 보통은 문자열입니다. - 값은 어떤 자료형도 가능합니다. -<<<<<<< HEAD 아래와 같은 방법을 사용하면 프로퍼티에 접근할 수 있습니다. - 점 표기법: `obj.property` - 대괄호 표기법 `obj["property"]`. 대괄호 표기법을 사용하면 `obj[varWithKey]`같이 변수에서 키를 가져올 수 있습니다. -======= -To access a property, we can use: -- The dot notation: `obj.property`. -- Square brackets notation `obj["property"]`. Square brackets allow taking the key from a variable, like `obj[varWithKey]`. ->>>>>>> upstream/master 객체엔 다음과 같은 추가 연산자를 사용할 수 있습니다. - 프로퍼티를 삭제하고 싶을 때: `delete obj.prop` From f623a8f47b2fb5d0b50db69230a00ad7a06228b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Thu, 14 May 2026 21:18:50 +0900 Subject: [PATCH 02/21] =?UTF-8?q?docs:=20=EA=B0=9D=EC=B2=B4=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=8D=BC=ED=8B=B0=20=EC=84=A4=EB=AA=85=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=ED=91=9C=ED=98=84=20=EB=B3=B4=EC=99=84=20(read?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=95=B4=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 63412c01fa..840f1428ed 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -44,7 +44,7 @@ let user = { // 객체 ![user object](object-user.svg) -서랍장에 파일을 추가하고 뺄 수 있듯이 개발자는 프로퍼티를 추가, 삭제할 수 있습니다. +서랍장에 파일을 추가하고, 꺼내 읽고, 뺄 수 있듯이 개발자는 프로퍼티를 추가, 조회, 삭제할 수 있습니다. 점 표기법(dot notation)을 이용하면 프로퍼티 값을 읽는 것도 가능합니다. From 5b9799b06ad0d4278ad3b309e0f957e72f74e376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Thu, 14 May 2026 21:49:18 +0900 Subject: [PATCH 03/21] =?UTF-8?q?docs:=20js/04-object-basic/02-object-copy?= =?UTF-8?q?=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-object-copy/article.md | 208 ------------------ 1 file changed, 208 deletions(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index f614c8e472..5888a27f1c 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD # 참조에 의한 객체 복사 객체와 원시 타입의 근본적인 차이 중 하나는 객체는 '참조에 의해(by reference)' 저장되고 복사된다는 것입니다. @@ -6,24 +5,12 @@ 원시값(문자열, 숫자, 불린 값)은 '값 그대로' 저장·할당되고 복사되는 반면에 말이죠. 예시: -======= -# Object references and copying - -One of the fundamental differences of objects versus primitives is that objects are stored and copied "by reference", whereas primitive values: strings, numbers, booleans, etc -- are always copied "as a whole value". - -That's easy to understand if we look a bit under the hood of what happens when we copy a value. - -Let's start with a primitive, such as a string. - -Here we put a copy of `message` into `phrase`: ->>>>>>> upstream/master ```js let message = "Hello!"; let phrase = message; ``` -<<<<<<< HEAD 예시를 실행하면 두 개의 독립된 변수에 각각 문자열 `"Hello!"`가 저장됩니다. ![](variable-copy-value.svg) @@ -33,19 +20,6 @@ let phrase = message; **변수엔 객체가 그대로 저장되는 것이 아니라, 객체가 저장되어있는 '메모리 주소'인 객체에 대한 '참조 값'이 저장됩니다.** 그림을 통해 변수 user에 객체를 할당할 때 무슨 일이 일어나는지 알아봅시다. -======= -As a result we have two independent variables, each one storing the string `"Hello!"`. - -![](variable-copy-value.svg) - -Quite an obvious result, right? - -Objects are not like that. - -**A variable assigned to an object stores not the object itself, but its "address in memory" -- in other words "a reference" to it.** - -Let's look at an example of such a variable: ->>>>>>> upstream/master ```js let user = { @@ -57,21 +31,9 @@ And here's how it's actually stored in memory: ![](variable-contains-reference.svg) -<<<<<<< HEAD 객체는 메모리 내 어딘가에 저장되고, 변수 `user`엔 객체를 '참조'할 수 있는 값이 저장됩니다. 따라서 **객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않습니다.** -======= -The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it. - -We may think of an object variable, such as `user`, like a sheet of paper with the address of the object on it. - -When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object. - -Now here's why it's important. - -**When an object variable is copied, the reference is copied, but the object itself is not duplicated.** ->>>>>>> upstream/master 예시: @@ -81,21 +43,11 @@ let user = { name: "John" }; let admin = user; // 참조값을 복사함 ``` -<<<<<<< HEAD 변수는 두 개이지만 각 변수엔 동일 객체에 대한 참조 값이 저장되죠. ![](variable-copy-reference.svg) 따라서 객체에 접근하거나 객체를 조작할 땐 여러 변수를 사용할 수 있습니다. -======= -Now we have two variables, each storing a reference to the same object: - -![](variable-copy-reference.svg) - -As you can see, there's still one object, but now with two variables that reference it. - -We can use either variable to access the object and modify its contents: ->>>>>>> upstream/master ```js run let user = { name: 'John' }; @@ -109,25 +61,15 @@ admin.name = 'Pete'; // 'admin' 참조 값에 의해 변경됨 alert(*!*user.name*/!*); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함 ``` -<<<<<<< HEAD 객체를 서랍장에 비유하면 변수는 서랍장을 열 수 있는 열쇠라고 할 수 있습니다. 서랍장은 하나, 서랍장을 열 수 있는 열쇠는 두 개인데, 그중 하나(`admin`)를 사용해 서랍장을 열어 정돈한 후, 또 다른 열쇠로 서랍장을 열면 정돈된 내용을 볼 수 있습니다. -======= -It's as if we had a cabinet with two keys and used one of them (`admin`) to get into it and make changes. Then, if we later use another key (`user`), we are still opening the same cabinet and can access the changed contents. ->>>>>>> upstream/master ### 참조에 의한 비교 -<<<<<<< HEAD 객체 비교 시 동등 연산자 `==`와 일치 연산자 `===`는 동일하게 동작합니다. **비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참을 반환하죠.** 두 변수가 같은 객체를 참조하는 예시를 살펴봅시다. 일치·동등 비교 모두에서 참이 반환됩니다. -======= -Two objects are equal only if they are the same object. - -For instance, here `a` and `b` reference the same object, thus they are equal: ->>>>>>> upstream/master ```js run let a = {}; @@ -137,11 +79,7 @@ alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다. alert( a === b ); // true ``` -<<<<<<< HEAD 다른 예시를 살펴봅시다. 두 객체 모두 비어있다는 점에서 같아 보이지만, 독립된 객체이기 때문에 일치·동등 비교하면 거짓이 반환됩니다. -======= -And here two independent objects are not equal, even though they look alike (both are empty): ->>>>>>> upstream/master ```js run let a = {}; @@ -150,53 +88,17 @@ let b = {}; // 독립된 두 객체 alert( a == b ); // false ``` -<<<<<<< HEAD `obj1 > obj2` 같은 대소 비교나 `obj == 5` 같은 원시값과의 비교에선 객체가 원시형으로 변환됩니다. 객체가 어떻게 원시형으로 변하는지에 대해선 곧 학습할 예정인데, 이러한 비교(객체끼리의 대소 비교나 원시값과 객체를 비교하는 것)가 필요한 경우는 매우 드물긴 합니다. 대개 코딩 실수 때문에 이런 비교가 발생합니다. ## 객체 복사, 병합과 Object.assign -======= -For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake. - -````smart header="Const objects can be modified" -An important side effect of storing objects as references is that an object declared as `const` *can* be modified. - -For instance: - -```js run -const user = { - name: "John" -}; - -*!* -user.name = "Pete"; // (*) -*/!* - -alert(user.name); // Pete -``` - -It might seem that the line `(*)` would cause an error, but it does not. The value of `user` is constant, it must always reference the same object, but properties of that object are free to change. - -In other words, the `const user` gives an error only if we try to set `user=...` as a whole. - -That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter . -```` - -## Cloning and merging, Object.assign [#cloning-and-merging-object-assign] ->>>>>>> upstream/master 객체가 할당된 변수를 복사하면 동일한 객체에 대한 참조 값이 하나 더 만들어진다는 걸 배웠습니다. -<<<<<<< HEAD 그런데 객체를 복제하고 싶다면 어떻게 해야 할까요? 기존에 있던 객체와 똑같으면서 독립적인 객체를 만들고 싶다면 말이죠. 방법은 있는데 자바스크립트는 객체 복제 내장 메서드를 지원하지 않기 때문에 조금 어렵습니다. 사실 객체를 복제해야 할 일은 거의 없습니다. 참조에 의한 복사로 해결 가능한 일이 대다수이죠. 정말 복제가 필요한 상황이라면 새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 원시 수준까지 프로퍼티를 복사하면 됩니다. -======= -But what if we need to duplicate an object? - -We can create a new object and replicate the structure of the existing one, by iterating over its properties and copying them on the primitive level. ->>>>>>> upstream/master 아래와 같이 말이죠. @@ -221,11 +123,7 @@ clone.name = "Pete"; // clone의 데이터를 변경합니다. alert( user.name ); // 기존 객체에는 여전히 John이 있습니다. ``` -<<<<<<< HEAD [Object.assign](mdn:js/Object/assign)를 사용하는 방법도 있습니다. -======= -We can also use the method [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). ->>>>>>> upstream/master 문법과 동작 방식은 다음과 같습니다. @@ -233,7 +131,6 @@ We can also use the method [Object.assign](https://developer.mozilla.org/en-US/d Object.assign(dest, ...sources) ``` -<<<<<<< HEAD - 첫 번째 인수 `dest`는 목표로 하는 객체입니다. - 이어지는 인수 `src1, ..., srcN`는 복사하고자 하는 객체입니다. `...`은 필요에 따라 얼마든지 많은 객체를 인수로 사용할 수 있다는 것을 나타냅니다. - 객체 `src1, ..., srcN`의 프로퍼티를 `dest`에 복사합니다. `dest`를 제외한 인수(객체)의 프로퍼티 전부가 첫 번째 인수(객체)로 복사됩니다. @@ -241,16 +138,6 @@ Object.assign(dest, ...sources) `assign` 메서드를 사용해 여러 객체를 하나로 병합하는 예시를 살펴봅시다. ```js -======= -- The first argument `dest` is a target object. -- Further arguments is a list of source objects. - -It copies the properties of all source objects into the target `dest`, and then returns it as the result. - -For example, we have `user` object, let's add a couple of permissions to it: - -```js run ->>>>>>> upstream/master let user = { name: "John" }; let permissions1 = { canView: true }; @@ -277,11 +164,7 @@ Object.assign(user, { name: "Pete" }); alert(user.name); // user = { name: "Pete" } ``` -<<<<<<< HEAD `Object.assign`을 사용하면 반복문 없이도 간단하게 객체를 복사할 수 있습니다. -======= -We also can use `Object.assign` to perform a simple object cloning: ->>>>>>> upstream/master ```js run let user = { @@ -297,21 +180,11 @@ alert(clone.name); // John alert(clone.age); // 30 ``` -<<<<<<< HEAD 예시를 실행하면 `user`에 있는 모든 프로퍼티가 빈 배열에 복사되고 변수에 할당됩니다. -======= -Here it copies all properties of `user` into the empty object and returns it. - -There are also other methods of cloning an object, e.g. using the [spread syntax](info:rest-parameters-spread) `clone = {...user}`, covered later in the tutorial. ->>>>>>> upstream/master ## 중첩 객체 복사 -<<<<<<< HEAD 지금까진 `user`의 모든 프로퍼티가 원시값인 경우만 가정했습니다. 그런데 프로퍼티는 다른 객체에 대한 참조 값일 수도 있습니다. 이 경우는 어떻게 해야 할까요? -======= -Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. ->>>>>>> upstream/master 아래와 같이 말이죠. ```js run @@ -326,13 +199,9 @@ let user = { alert( user.sizes.height ); // 182 ``` -<<<<<<< HEAD `clone.sizes = user.sizes`로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없습니다. `user.sizes`는 객체이기 때문에 참조 값이 복사되기 때문입니다. `clone.sizes = user.sizes`로 프로퍼티를 복사하면 `clone`과 `user`는 같은 sizes를 공유하게 됩니다. 아래와 같이 말이죠. -======= -Now it's not enough to copy `clone.sizes = user.sizes`, because `user.sizes` is an object, and will be copied by reference, so `clone` and `user` will share the same sizes: ->>>>>>> upstream/master ```js run let user = { @@ -347,7 +216,6 @@ let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, 같은 객체입니다. -<<<<<<< HEAD // user와 clone는 sizes를 공유합니다. user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다. alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다. @@ -358,87 +226,11 @@ alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 깊은 복사 시 사용되는 표준 알고리즘인 [Structured cloning algorithm](https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data)을 사용하면 위 사례를 비롯한 다양한 상황에서 객체를 복제할 수 있습니다. 자바스크립트 라이브러리 [lodash](https://lodash.com)의 메서드인 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)을 사용하면 이 알고리즘을 직접 구현하지 않고도 깊은 복사를 처리할 수 있으므로 참고하시기 바랍니다. -======= -// user and clone share sizes -user.sizes.width = 60; // change a property from one place -alert(clone.sizes.width); // 60, get the result from the other one -``` - -To fix that and make `user` and `clone` truly separate objects, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning" or "structured cloning". There's [structuredClone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) method that implements deep cloning. - - -### structuredClone - -The call `structuredClone(object)` clones the `object` with all nested properties. - -Here's how we can use it in our example: - -```js run -let user = { - name: "John", - sizes: { - height: 182, - width: 50 - } -}; - -*!* -let clone = structuredClone(user); -*/!* - -alert( user.sizes === clone.sizes ); // false, different objects - -// user and clone are totally unrelated now -user.sizes.width = 60; // change a property from one place -alert(clone.sizes.width); // 50, not related -``` - -The `structuredClone` method can clone most data types, such as objects, arrays, primitive values. - -It also supports circular references, when an object property references the object itself (directly or via a chain or references). - -For instance: - -```js run -let user = {}; -// let's create a circular reference: -// user.me references the user itself -user.me = user; - -let clone = structuredClone(user); -alert(clone.me === clone); // true -``` - -As you can see, `clone.me` references the `clone`, not the `user`! So the circular reference was cloned correctly as well. - -Although, there are cases when `structuredClone` fails. - -For instance, when an object has a function property: - -```js run -// error -structuredClone({ - f: function() {} -}); -``` - -Function properties aren't supported. - -To handle such complex cases we may need to use a combination of cloning methods, write custom code or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com). ->>>>>>> upstream/master ## 요약 -<<<<<<< HEAD 객체는 참조에 의해 할당되고 복사됩니다. 변수엔 '객체' 자체가 아닌 메모리상의 주소인 '참조'가 저장됩니다. 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사됩니다. -======= -Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself. ->>>>>>> upstream/master 그리고 복사된 참조를 이용한 모든 작업(프로퍼티 추가·삭제 등)은 동일한 객체를 대상으로 이뤄집니다. -<<<<<<< HEAD 객체의 '진짜 복사본'을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 `Object.assign`이나 '깊은 복사'를 가능하게 해주는 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)를 사용하면 됩니다. 이때 얕은 복사본은 중첩 객체를 처리하지 못한다는 점을 기억해 두시기 바랍니다. -======= -To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function `structuredClone` or use a custom cloning implementation, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). ->>>>>>> upstream/master From d558c67e6aae421e2f4272ce5dc367810d00d3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Thu, 14 May 2026 22:05:10 +0900 Subject: [PATCH 04/21] =?UTF-8?q?docs:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 840f1428ed..4e857259a5 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -451,6 +451,7 @@ for (let code in codes) { 문자열 "49"는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티입니다. 하지만 '+49'와 '1.2'는 정수 프로퍼티가 아닙니다. ```js run +// Number(...)는 명시적으로 값을 숫자형으로 변환합니다. // 함수 Math.trunc는 소수점 아래를 버리고 숫자의 정수부만 반환합니다. alert( String(Math.trunc(Number("49"))) ); // '49'가 출력됩니다. 기존에 입력한 값과 같으므로 정수 프로퍼티입니다. alert( String(Math.trunc(Number("+49"))) ); // '49'가 출력됩니다. 기존에 입력한 값(+49)과 다르므로 정수 프로퍼티가 아닙니다. From 7e902164b2ad486140c3576ed3c9a904ddb06e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Thu, 14 May 2026 22:12:37 +0900 Subject: [PATCH 05/21] =?UTF-8?q?docs:=20=EB=B3=80=EC=88=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=84=A4=EB=AA=85=EC=97=90=EC=84=9C=20=ED=82=A4=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 4e857259a5..0b70ac9125 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -276,7 +276,7 @@ let user = { ## 프로퍼티 이름의 제약사항 -아시다시피 변수 이름(키)엔 'for', 'let', 'return' 같은 예약어를 사용하면 안됩니다. +아시다시피 변수 이름엔 'for', 'let', 'return' 같은 예약어를 사용하면 안됩니다. 그런데 객체 프로퍼티엔 이런 제약이 없습니다. From 5dd277f46795d2350017d63788c370369e0d00a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 11:46:06 +0900 Subject: [PATCH 06/21] =?UTF-8?q?docs:=20=EB=AF=B8=EB=B2=88=EC=97=AD=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=A5=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index 5888a27f1c..86a5f8bf25 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -27,7 +27,7 @@ let user = { }; ``` -And here's how it's actually stored in memory: +실제로는 메모리에 다음과 같이 저장됩니다. ![](variable-contains-reference.svg) From 2f9d9a7de9f319226d95419c773f41571161bd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 11:46:33 +0900 Subject: [PATCH 07/21] =?UTF-8?q?docs:=20=EB=88=84=EB=9D=BD=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=A5=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index 86a5f8bf25..e8df080c47 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -15,6 +15,8 @@ let phrase = message; ![](variable-copy-value.svg) +당연한 결과처럼 보이죠? + 그런데 객체의 동작 방식은 이와 다릅니다. **변수엔 객체가 그대로 저장되는 것이 아니라, 객체가 저장되어있는 '메모리 주소'인 객체에 대한 '참조 값'이 저장됩니다.** From 4e088418aca16e8340e1e0d1d21ae579181dc8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 11:49:45 +0900 Subject: [PATCH 08/21] =?UTF-8?q?docs:=20js/04-object-basic/03-garbage-col?= =?UTF-8?q?lection=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-garbage-collection/article.md | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 997971baef..104f0a2925 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -14,27 +14,16 @@ 예시: -<<<<<<< HEAD - 현재 함수의 지역 변수와 매개변수 - 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수 - 전역 변수 - 기타 등등 -======= - - The currently executing function, its local variables and parameters. - - Other functions on the current chain of nested calls, their local variables and parameters. - - Global variables. - - (there are some other, internal ones as well) ->>>>>>> upstream/master 이런 값은 *루트(root)* 라고 부릅니다. 2. 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값은 도달 가능한 값이 됩니다. -<<<<<<< HEAD 전역 변수에 객체가 저장되어있다고 가정해 봅시다. 이 객체의 프로퍼티가 또 다른 객체를 참조하고 있다면, 프로퍼티가 참조하는 객체는 도달 가능한 값이 됩니다. 이 객체가 참조하는 다른 모든 것들도 도달 가능하다고 여겨집니다. 자세한 예시는 아래에서 살펴보겠습니다. -======= - For instance, if there's an object in a global variable, and that object has a property referencing another object, *that* object is considered reachable. And those that it references are also reachable. Detailed examples to follow. ->>>>>>> upstream/master 자바스크립트 엔진 내에선 [가비지 컬렉터(garbage collector)](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science))가 끊임없이 동작합니다. 가비지 컬렉터는 모든 객체를 모니터링하고, 도달할 수 없는 객체는 삭제합니다. @@ -184,19 +173,11 @@ John과 Ann은 여전히 서로를 참조하고 있고, 두 객체 모두 외부 ![](garbage-collection-2.svg) -<<<<<<< HEAD 이후 루트가 참조하고 있는 것들을 mark 합니다. ![](garbage-collection-3.svg) 도달 가능한 모든 객체를 방문할 때까지, mark 한 객체가 참조하는 객체를 계속해서 mark 합니다. -======= -Then we follow their references and mark referenced objects: - -![](garbage-collection-3.svg) - -...And continue to follow further references, while possible: ->>>>>>> upstream/master ![](garbage-collection-4.svg) @@ -206,23 +187,13 @@ Then we follow their references and mark referenced objects: 루트에서 페인트를 들이붓는다고 상상하면 이 과정을 이해하기 쉽습니다. 루트를 시작으로 참조를 따라가면서 도달가능한 객체 모두에 페인트가 칠해진다고 생각하면 됩니다. 이때 페인트가 묻지 않은 객체는 메모리에서 삭제됩니다. -<<<<<<< HEAD 지금까지 가비지 컬렉션이 어떻게 동작하는지에 대한 개념을 알아보았습니다. 자바스크립트 엔진은 실행에 영향을 미치지 않으면서 가비지 컬렉션을 더 빠르게 하는 다양한 최적화 기법을 적용합니다. -======= -That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not introduce any delays into the code execution. ->>>>>>> upstream/master 최적화 기법: -<<<<<<< HEAD - **generational collection(세대별 수집)** -- 객체를 '새로운 객체'와 '오래된 객체'로 나눕니다. 객체 상당수는 생성 이후 제 역할을 빠르게 수행해 금방 쓸모가 없어지는데, 이런 객체를 '새로운 객체'로 구분합니다. 가비지 컬렉터는 이런 객체를 공격적으로 메모리에서 제거합니다. 일정 시간 이상 동안 살아남은 객체는 '오래된 객체'로 분류하고, 가비지 컬렉터가 덜 감시합니다. - **incremental collection(점진적 수집)** -- 방문해야 할 객체가 많다면 모든 객체를 한 번에 방문하고 mark 하는데 상당한 시간이 소모됩니다. 가비지 컬렉션에 많은 리소스가 사용되어 실행 속도도 눈에 띄게 느려지겠죠. 자바스크립트 엔진은 이런 현상을 개선하기 위해 가비지 컬렉션을 여러 부분으로 분리한 다음, 각 부분을 별도로 수행합니다. 작업을 분리하고, 변경 사항을 추적하는 데 추가 작업이 필요하긴 하지만, 긴 지연을 짧은 지연 여러 개로 분산시킬 수 있다는 장점이 있습니다. - **idle-time collection(유휴 시간 수집)** -- 가비지 컬렉터는 실행에 주는 영향을 최소화하기 위해 CPU가 유휴 상태일 때에만 가비지 컬렉션을 실행합니다. -======= -- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". In typical code, many objects have a short life span: they appear, do their job and die fast, so it makes sense to track new objects and clear the memory from them if that's the case. Those that survive for long enough, become "old" and are examined less often. -- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine splits the whole set of existing objects into multiple parts. And then clear these parts one after another. There are many small garbage collections instead of a total one. That requires some extra bookkeeping between them to track changes, but we get many tiny delays instead of a big one. -- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. ->>>>>>> upstream/master 이 외에도 다양한 최적화 기법과 가비지 컬렉션 알고리즘이 있습니다. 다양한 기법과 알고리즘을 소개해 드리고 싶지만, 엔진마다 세부 사항이나 기법이 다르기 때문에 여기서 멈추도록 하겠습니다. 엔진이 발전하면 기법도 달라지기 때문에 학습해야 할 이유가 진짜 없다면 '심화' 학습은 그리 가치 있지 않다고 생각합니다. 순수한 호기심 때문이라면 물론 괜찮습니다. 이런 분들을 위해 아래에 링크를 몇 개를 소개해놓았습니다. @@ -230,30 +201,16 @@ That's the concept of how garbage collection works. JavaScript engines apply man 지금까지 알아본 내용을 요약해 봅시다. -<<<<<<< HEAD - 가비지 컬렉션은 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없습니다. - 객체는 도달 가능한 상태일 때 메모리에 남습니다. - 참조된다고 해서 도달 가능한 것은 아닙니다. 서로 연결된 객체들도 도달 불가능할 수 있습니다. -======= -- Garbage collection is performed automatically. We cannot force or prevent it. -- Objects are retained in memory while they are reachable. -- Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole, as we've seen in the example above. ->>>>>>> upstream/master 모던 자바스크립트 엔진은 좀 더 발전된 가비지 컬렉션 알고리즘을 사용합니다. 어떤 알고리즘을 사용하는지 궁금하다면 'The Garbage Collection Handbook: The Art of Automatic Memory Management'(저자 - R. Jones et al)를 참고하시기 바랍니다. -<<<<<<< HEAD 저수준(low-level) 프로그래밍에 익숙하다면, [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection)을 읽어보세요. V8 가비지 컬렉터에 대한 자세한 내용을 확인해 볼 수 있습니다. [V8 공식 블로그](https://v8.dev/)에도 메모리 관리 방법 변화에 대한 내용이 올라옵니다. 가비지 컬렉션을 심도 있게 학습하려면 V8 내부구조를 공부하거나 V8 엔지니어로 일했던 [Vyacheslav Egorov](http://mrale.ph)의 블로그를 읽는 것도 좋습니다. 여러 엔진 중 'V8' 엔진을 언급하는 이유는 인터넷에서 관련 글을 쉽게 찾을 수 있기 때문입니다. V8과 타 엔진들은 동작 방법이 비슷한데, 가비지 컬렉션 동작 방식에는 많은 차이가 있습니다. 저수준 최적화가 필요한 상황이라면, 엔진에 대한 조예가 깊어야 합니다. 먼저 자바스크립트에 익숙해진 후에 엔진에 대해 학습하는 것을 추천해 드립니다. -======= -If you are familiar with low-level programming, more detailed information about V8's garbage collector is in the article [A tour of V8: Garbage Collection](https://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). - -The [V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn more about garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](https://mrale.ph) who worked as one of the V8 engineers. I'm saying: "V8", because it is best covered by articles on the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. - -In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. ->>>>>>> upstream/master From 50343e292204af32e71688af07e80772e16448b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 12:08:09 +0900 Subject: [PATCH 09/21] =?UTF-8?q?docs:=20js/04-object-basics/04-object-met?= =?UTF-8?q?hods/7-calculator=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../04-object-basics/04-object-methods/7-calculator/task.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/1-js/04-object-basics/04-object-methods/7-calculator/task.md b/1-js/04-object-basics/04-object-methods/7-calculator/task.md index a588bba126..4721ef3ddc 100644 --- a/1-js/04-object-basics/04-object-methods/7-calculator/task.md +++ b/1-js/04-object-basics/04-object-methods/7-calculator/task.md @@ -6,15 +6,9 @@ importance: 5 `calculator`라는 객체를 만들고 세 메서드를 구현해 봅시다. -<<<<<<< HEAD - `read()`에선 프롬프트 창을 띄우고 더할 값 두 개를 입력받습니다. 입력받은 값은 객체의 프로퍼티에 저장합니다. - `sum()`은 저장된 두 값의 합을 반환합니다. - `mul()`은 저장된 두 값의 곱을 반환합니다. -======= -- `read()` prompts for two values and saves them as object properties with names `a` and `b` respectively. -- `sum()` returns the sum of saved values. -- `mul()` multiplies saved values and returns the result. ->>>>>>> upstream/master ```js let calculator = { From ab6bd4818ca4ba7443d9d8478c507f69643bef32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 12:08:54 +0900 Subject: [PATCH 10/21] =?UTF-8?q?docs:=20'code'=20=EB=B2=88=EC=97=AD=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/04-object-methods/7-calculator/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/04-object-methods/7-calculator/task.md b/1-js/04-object-basics/04-object-methods/7-calculator/task.md index 4721ef3ddc..7ca8afe81f 100644 --- a/1-js/04-object-basics/04-object-methods/7-calculator/task.md +++ b/1-js/04-object-basics/04-object-methods/7-calculator/task.md @@ -12,7 +12,7 @@ importance: 5 ```js let calculator = { - // ... 여기에 답안 작성 ... + // ... 여기에 코드 작성 ... }; calculator.read(); From abc8aad765520e90e2c282b28ba51463abb76465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=EC=98=81?= Date: Sat, 16 May 2026 12:09:25 +0900 Subject: [PATCH 11/21] =?UTF-8?q?docs:=20js/04-object-basics/04-object-met?= =?UTF-8?q?hods/8-chain-calls=20=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../04-object-methods/8-chain-calls/task.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md index da207d22d2..02719e434d 100644 --- a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md +++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md @@ -4,11 +4,7 @@ importance: 2 # 체이닝 -<<<<<<< HEAD 올라가기(`up`)와 내려가기(`down`) 메서드를 제공하는 객체 `ladder`가 있습니다. -======= -There's a `ladder` object that allows you to go up and down: ->>>>>>> upstream/master ```js let ladder = { @@ -25,11 +21,7 @@ let ladder = { }; ``` -<<<<<<< HEAD 메서드를 연이어 호출하고자 한다면 아래와 같이 코드를 작성할 수 있습니다. -======= -Now, if we need to make several calls in sequence, we can do it like this: ->>>>>>> upstream/master ```js ladder.up(); @@ -40,18 +32,10 @@ ladder.down(); ladder.showStep(); // 0 ``` -<<<<<<< HEAD `up`, `down`, `showStep`을 수정해 아래처럼 메서드 호출 체이닝이 가능하도록 해봅시다. -======= -Modify the code of `up`, `down`, and `showStep` to make the calls chainable, like this: ->>>>>>> upstream/master ```js ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0 ``` -<<<<<<< HEAD 참고로 이런 방식은 자바스크립트 라이브러리에서 널리 사용됩니다. -======= -Such an approach is widely used across JavaScript libraries. ->>>>>>> upstream/master From c1b46ea339b22df493ce8c435d29a9b60119ec79 Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sat, 16 May 2026 23:27:02 +0900 Subject: [PATCH 12/21] =?UTF-8?q?docs:=20js/04-object-basics/03-garbage-co?= =?UTF-8?q?llection=20=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/03-garbage-collection/article.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 104f0a2925..8ef2a634f8 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -74,11 +74,7 @@ let admin = user; user = null; ``` -<<<<<<< HEAD 전역 변수 `admin`을 통하면 여전히 객체 John에 접근할 수 있기 때문에 John은 메모리에서 삭제되지 않습니다. 이 상태에서 `admin`을 다른 값(null 등)으로 덮어쓰면 John은 메모리에서 삭제될 수 있습니다. -======= -...Then the object is still reachable via `admin` global variable, so it must stay in memory. If we overwrite `admin` too, then it can be removed. ->>>>>>> upstream/master ## 연결된 객체 From 5dcbeed450e11c814fe7137b0d8859e5fe4617d9 Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sat, 16 May 2026 23:43:43 +0900 Subject: [PATCH 13/21] =?UTF-8?q?doc:=20=EB=88=84=EB=9D=BD=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-object-copy/article.md | 107 ++++++++++++++++-- 1 file changed, 96 insertions(+), 11 deletions(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index e8df080c47..bcaafdde78 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -4,7 +4,11 @@ 원시값(문자열, 숫자, 불린 값)은 '값 그대로' 저장·할당되고 복사되는 반면에 말이죠. -예시: +값을 복사할 때 내부에서 어떤 일이 일어나는지 살펴보면 이해하기 쉽습니다. + +먼저 문자열 같은 원시값부터 살펴봅시다. + +아래에선 `message`의 복사본을 `phrase`에 넣습니다. ```js let message = "Hello!"; @@ -92,7 +96,31 @@ alert( a == b ); // false `obj1 > obj2` 같은 대소 비교나 `obj == 5` 같은 원시값과의 비교에선 객체가 원시형으로 변환됩니다. 객체가 어떻게 원시형으로 변하는지에 대해선 곧 학습할 예정인데, 이러한 비교(객체끼리의 대소 비교나 원시값과 객체를 비교하는 것)가 필요한 경우는 매우 드물긴 합니다. 대개 코딩 실수 때문에 이런 비교가 발생합니다. -## 객체 복사, 병합과 Object.assign +````smart header="상수 객체는 수정될 수 있습니다." +객체가 참조로 저장된다는 사실 때문에 생기는 중요한 부수 효과가 있습니다. `const`로 선언된 객체도 *수정할 수 있습니다*. + +예시: + +```js run +const user = { + name: "John" +}; + +*!* +user.name = "Pete"; // (*) +*/!* + +alert(user.name); // Pete +``` + +`(*)`로 표시한 줄에서 오류가 발생할 것처럼 보일 수 있지만 그렇지 않습니다. `user`의 값은 상수이므로 항상 같은 객체를 참조해야 하지만, 그 객체의 프로퍼티는 자유롭게 변경할 수 있습니다. + +다시 말해, `const user`는 `user=...`처럼 `user` 전체에 새 값을 대입하려고 할 때만 오류를 일으킵니다. + +그렇지만 객체 프로퍼티까지 상수로 만들어야 한다면 완전히 다른 방법을 써야 합니다. 이 방법은 챕터에서 다룹니다. +```` + +## 객체 복사, 병합과 Object.assign [#cloning-and-merging-object-assign] 객체가 할당된 변수를 복사하면 동일한 객체에 대한 참조 값이 하나 더 만들어진다는 걸 배웠습니다. @@ -150,7 +178,7 @@ let permissions2 = { canEdit: true }; Object.assign(user, permissions1, permissions2); */!* -// now user = { name: "John", canView: true, canEdit: true } +// 이제 user = { name: "John", canView: true, canEdit: true } alert(user.name); // John alert(user.canView); // true alert(user.canEdit); // true @@ -182,7 +210,9 @@ alert(clone.name); // John alert(clone.age); // 30 ``` -예시를 실행하면 `user`에 있는 모든 프로퍼티가 빈 배열에 복사되고 변수에 할당됩니다. +예시를 실행하면 `user`에 있는 모든 프로퍼티가 빈 객체에 복사되고, 그 객체가 반환됩니다. + +객체를 복제하는 다른 방법도 있습니다. 예를 들어 튜토리얼 뒷부분에서 다룰 [스프레드 문법](info:rest-parameters-spread)을 사용하면 `clone = {...user}`처럼 객체를 복제할 수 있습니다. ## 중첩 객체 복사 @@ -218,16 +248,71 @@ let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, 같은 객체입니다. -// user와 clone는 sizes를 공유합니다. -user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다. -alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다. +// user와 clone은 sizes를 공유합니다. +user.sizes.width = 60; // 한 객체에서 프로퍼티를 변경합니다. +alert(clone.sizes.width); // 60, 다른 객체에서 변경 사항을 확인할 수 있습니다. ``` -이 문제를 해결하려면 `user[key]`의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복사해주는 반복문을 사용해야 합니다. 이런 방식을 '깊은 복사(deep cloning)'라고 합니다. +이 문제를 해결해 `user`와 `clone`을 진짜로 독립된 객체로 만들려면 `user[key]`의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복제하는 반복문을 사용해야 합니다. 이런 방식을 '깊은 복사(deep cloning)' 또는 '구조화 복사(structured cloning)'라고 합니다. 깊은 복사를 구현한 [structuredClone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) 메서드가 있습니다. + +### structuredClone + +`structuredClone(object)`을 호출하면 중첩 프로퍼티까지 모두 포함해 `object`가 복제됩니다. + +앞선 예시에 이 메서드를 적용해 봅시다. + +```js run +let user = { + name: "John", + sizes: { + height: 182, + width: 50 + } +}; + +*!* +let clone = structuredClone(user); +*/!* + +alert( user.sizes === clone.sizes ); // false, 서로 다른 객체입니다. + +// 이제 user와 clone은 완전히 독립적입니다. +user.sizes.width = 60; // 한 객체에서 프로퍼티를 변경합니다. +alert(clone.sizes.width); // 50, 다른 객체에는 영향을 주지 않습니다. +``` + +`structuredClone` 메서드는 객체, 배열, 원시값 등 대부분의 자료형을 복제할 수 있습니다. + +객체 프로퍼티가 객체 자신을 직접 또는 여러 참조를 거쳐 참조하는 순환 참조도 지원합니다. + +예시: + +```js run +let user = {}; +// 순환 참조를 만들어 봅시다. +// user.me는 user 자신을 참조합니다. +user.me = user; + +let clone = structuredClone(user); +alert(clone.me === clone); // true +``` + +보시다시피 `clone.me`는 `user`가 아니라 `clone`을 참조합니다. 순환 참조도 올바르게 복제된 것입니다. + +다만 `structuredClone`이 실패하는 경우도 있습니다. + +예를 들어 객체에 함수 프로퍼티가 있으면 실패합니다. + +```js run +// 에러가 발생합니다. +structuredClone({ + f: function() {} +}); +``` -깊은 복사 시 사용되는 표준 알고리즘인 [Structured cloning algorithm](https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data)을 사용하면 위 사례를 비롯한 다양한 상황에서 객체를 복제할 수 있습니다. +함수 프로퍼티는 지원되지 않습니다. -자바스크립트 라이브러리 [lodash](https://lodash.com)의 메서드인 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)을 사용하면 이 알고리즘을 직접 구현하지 않고도 깊은 복사를 처리할 수 있으므로 참고하시기 바랍니다. +이처럼 복잡한 경우를 처리하려면 여러 복제 방법을 조합하거나 직접 코드를 작성해야 할 수 있습니다. 바퀴를 다시 발명하지 않으려면 자바스크립트 라이브러리 [lodash](https://lodash.com)의 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) 같은 기존 구현을 사용할 수도 있습니다. ## 요약 @@ -235,4 +320,4 @@ alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 그리고 복사된 참조를 이용한 모든 작업(프로퍼티 추가·삭제 등)은 동일한 객체를 대상으로 이뤄집니다. -객체의 '진짜 복사본'을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 `Object.assign`이나 '깊은 복사'를 가능하게 해주는 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep)를 사용하면 됩니다. 이때 얕은 복사본은 중첩 객체를 처리하지 못한다는 점을 기억해 두시기 바랍니다. +객체의 '진짜 복사본'(클론)을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 `Object.assign`을 사용하거나(중첩 객체는 참조로 복사됩니다), '깊은 복사' 함수인 `structuredClone` 혹은 [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) 같은 기존 구현을 사용할 수 있습니다. From 7adabe4bfa21613b5b2faadfb44027742a2692a9 Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sat, 16 May 2026 23:44:08 +0900 Subject: [PATCH 14/21] =?UTF-8?q?doc:=20=EC=A3=BC=EC=84=9D=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/04-object-methods/8-chain-calls/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md index 02719e434d..7c89c19027 100644 --- a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md +++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md @@ -35,7 +35,7 @@ ladder.showStep(); // 0 `up`, `down`, `showStep`을 수정해 아래처럼 메서드 호출 체이닝이 가능하도록 해봅시다. ```js -ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0 +ladder.up().up().down().showStep().down().showStep(); // 1과 0을 차례대로 보여줌 ``` 참고로 이런 방식은 자바스크립트 라이브러리에서 널리 사용됩니다. From 41dba6453146c6af6330846a3c720d1309d3d2bb Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sat, 16 May 2026 23:45:18 +0900 Subject: [PATCH 15/21] =?UTF-8?q?docs:=20=EC=A0=95=ED=99=95=ED=95=9C=20?= =?UTF-8?q?=EC=9D=98=EB=AF=B8=20=EC=A0=84=EB=8B=AC=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=B2=88=EC=97=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/04-object-methods/7-calculator/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/04-object-methods/7-calculator/task.md b/1-js/04-object-basics/04-object-methods/7-calculator/task.md index 7ca8afe81f..efafae38a7 100644 --- a/1-js/04-object-basics/04-object-methods/7-calculator/task.md +++ b/1-js/04-object-basics/04-object-methods/7-calculator/task.md @@ -6,7 +6,7 @@ importance: 5 `calculator`라는 객체를 만들고 세 메서드를 구현해 봅시다. -- `read()`에선 프롬프트 창을 띄우고 더할 값 두 개를 입력받습니다. 입력받은 값은 객체의 프로퍼티에 저장합니다. +- `read()`에선 프롬프트 창을 띄우고 더할 값 두 개를 입력받습니다. 입력받은 값은 각각 `a`와 `b`라는 이름의 객체 프로퍼티에 저장합니다. - `sum()`은 저장된 두 값의 합을 반환합니다. - `mul()`은 저장된 두 값의 곱을 반환합니다. From 0fed58fce4d77aebe09af7c304f1a745130cb9ce Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sat, 16 May 2026 23:54:57 +0900 Subject: [PATCH 16/21] =?UTF-8?q?docs:=20=EC=B5=9C=EC=8B=A0=20=EC=9B=90?= =?UTF-8?q?=EB=AC=B8=20=EA=B5=AC=EC=A1=B0=EC=97=90=20=EB=A7=9E=EC=B6=B0=20?= =?UTF-8?q?`02-object-copy/article.md`=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 23 ---------------------- 1 file changed, 23 deletions(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 0b70ac9125..3e2080ecb0 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -92,29 +92,6 @@ let user = { ``` 이런 쉼표를 'trailing(길게 늘어지는)' 혹은 'hanging(매달리는)' 쉼표라고 부릅니다. 이렇게 끝에 쉼표를 붙이면 모든 프로퍼티가 유사한 형태를 보이기 때문에 프로퍼티를 추가, 삭제, 이동하는 게 쉬워집니다. -````smart header="상수 객체는 수정될 수 있습니다." -주의하세요. `const`로 선언된 객체는 수정될 수 있습니다. - -예시: - -```js run -const user = { - name: "John" -}; - -*!* -user.name = "Pete"; // (*) -*/!* - -alert(user.name); // Pete -``` - -`(*)`로 표시한 줄에서 오류를 일으키는 것처럼 보일 수 있지만 그렇지 않습니다. `const`는 `user`의 값을 고정하지만, 그 내용은 고정하지 않습니다. - -`const`는 `user=...`를 전체적으로 설정하려고 할 때만 오류가 발생합니다. - -상수 객체 프로퍼티를 만드는 또 다른 방법이 있습니다. 이후에 챕터에서 다루겠습니다. -```` ## 대괄호 표기법 From deceb26c96163cfc133d8ff43d76bde2b3a5eb0b Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sun, 17 May 2026 17:48:21 +0900 Subject: [PATCH 17/21] =?UTF-8?q?docs:=20forin=20=EB=88=84=EB=9D=BD=20?= =?UTF-8?q?=EC=95=B5=EC=BB=A4=ED=83=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/01-object/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 3e2080ecb0..190a6f6780 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -356,7 +356,7 @@ alert( "test" in obj ); // `in`을 사용하면 프로퍼티 유무를 제대로 `undefined`는 변수는 정의되어 있으나 값이 할당되지 않은 경우에 쓰기 때문에 프로퍼티 값이 `undefined`인 경우는 흔치 않습니다. 값을 '알 수 없거나(unknown)' 값이 '비어 있다는(empty)' 것을 나타낼 때는 주로 `null`을 사용합니다. 위 예시에서 `in` 연산자는 자리에 어울리지 않는 초대손님처럼 보이네요. -## 'for..in' 반복문 +## 'for..in' 반복문 [#forin] `for..in` 반복문을 사용하면 객체의 모든 키를 순회할 수 있습니다. `for..in`은 앞서 학습했던 `for(;;)` 반복문과는 완전히 다릅니다. From d34736f3526cbefc9ab212125b9d5b9612e33525 Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sun, 17 May 2026 18:03:29 +0900 Subject: [PATCH 18/21] =?UTF-8?q?docs:=20=EC=B0=B8=EC=A1=B0=EC=97=90=20?= =?UTF-8?q?=EC=9D=98=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=EB=B3=B5=EC=82=AC=20?= =?UTF-8?q?=EB=88=84=EB=9D=BD=20=ED=95=B4=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index bcaafdde78..4f80ac7ddc 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -37,9 +37,15 @@ let user = { ![](variable-contains-reference.svg) -객체는 메모리 내 어딘가에 저장되고, 변수 `user`엔 객체를 '참조'할 수 있는 값이 저장됩니다. +객체는 메모리 어딘가(그림 오른쪽)에 저장되고, 변수 `user`(그림 왼쪽)엔 객체를 '참조'할 수 있는 값이 저장됩니다. -따라서 **객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않습니다.** +객체 변수 `user`는 객체 주소가 적힌 종이 한 장이라고 생각할 수 있습니다. + +`user.name`처럼 객체를 대상으로 작업을 수행하면 자바스크립트 엔진은 그 주소로 이동해 실제 객체에 작업을 수행합니다. + +이 점이 중요한 이유를 살펴봅시다. + +**객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않습니다.** 예시: From 7ec184842500cf8b3b55a7fe2624da67a0650edc Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sun, 17 May 2026 18:08:03 +0900 Subject: [PATCH 19/21] =?UTF-8?q?docs:=20=EC=84=9C=EB=9E=8D=EC=9E=A5=20?= =?UTF-8?q?=EB=B9=84=EC=9C=A0=20=EB=AC=B8=EC=9E=A5=20user=20=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=B9=84=EC=9C=A0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index 4f80ac7ddc..3d5502cd85 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -73,7 +73,7 @@ admin.name = 'Pete'; // 'admin' 참조 값에 의해 변경됨 alert(*!*user.name*/!*); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함 ``` -객체를 서랍장에 비유하면 변수는 서랍장을 열 수 있는 열쇠라고 할 수 있습니다. 서랍장은 하나, 서랍장을 열 수 있는 열쇠는 두 개인데, 그중 하나(`admin`)를 사용해 서랍장을 열어 정돈한 후, 또 다른 열쇠로 서랍장을 열면 정돈된 내용을 볼 수 있습니다. +객체를 서랍장에 비유하면, 변수는 서랍장을 열 수 있는 열쇠라고 할 수 있습니다. 서랍장은 하나뿐이지만, 이를 여는 열쇠는 두 개 있는 셈입니다. 그중 하나인 `admin`으로 서랍장을 열어 내용을 변경하면, 나중에 다른 열쇠인 `user`로 같은 서랍장을 열었을 때도 변경된 내용을 확인할 수 있습니다. ### 참조에 의한 비교 From db1c21f36c5d409a18805f715fbeb762d240d9dd Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sun, 17 May 2026 18:12:56 +0900 Subject: [PATCH 20/21] =?UTF-8?q?docs:=20=EC=B0=B8=EC=A1=B0=EC=97=90=20?= =?UTF-8?q?=EC=9D=98=ED=95=9C=20=EB=B9=84=EA=B5=90=20=EB=B2=88=EC=97=AD=20?= =?UTF-8?q?=EB=88=84=EB=9D=BD=20=EB=AC=B8=EC=9E=A5=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index 3d5502cd85..4002abbb1a 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -83,6 +83,8 @@ alert(*!*user.name*/!*); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 두 변수가 같은 객체를 참조하는 예시를 살펴봅시다. 일치·동등 비교 모두에서 참이 반환됩니다. +예를 들어 아래 코드에서 `a`와 `b`는 같은 객체를 참조하므로 동등하다고 평가됩니다. + ```js run let a = {}; let b = a; // 참조에 의한 복사 From 43f80804336adeb884e6a2c1da215bd3eaf6fc74 Mon Sep 17 00:00:00 2001 From: jjyy0804 Date: Sun, 17 May 2026 20:39:35 +0900 Subject: [PATCH 21/21] =?UTF-8?q?docs:=20=EC=9B=90=EB=AC=B8=EC=9D=98=20js?= =?UTF-8?q?=20run=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/04-object-basics/02-object-copy/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index 4002abbb1a..ae27cd9026 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -175,7 +175,7 @@ Object.assign(dest, ...sources) - 마지막으로 `dest`를 반환합니다. `assign` 메서드를 사용해 여러 객체를 하나로 병합하는 예시를 살펴봅시다. -```js +```js run let user = { name: "John" }; let permissions1 = { canView: true };