diff --git a/1-js/06-advanced-functions/07-new-function/article.md b/1-js/06-advanced-functions/07-new-function/article.md index adb621d440..011d028244 100644 --- a/1-js/06-advanced-functions/07-new-function/article.md +++ b/1-js/06-advanced-functions/07-new-function/article.md @@ -92,11 +92,7 @@ getFunc()(); // getFunc의 렉시컬 환경에 있는 값 *!*"test"*/!*가 출 그런데 스크립트가 프로덕션 서버에 반영되기 전, *압축기(minifier)* 에 의해 압축될 때 문제가 발생합니다. 압축기는 스크립트에서 주석이나 여분의 공백 등을 없애 코드 크기를 줄여주는 특수한 프로그램인데 압축기가 지역 변수 이름을 짧게 바꾸면서 문제가 발생하죠. -<<<<<<< HEAD -구체적으로 어떤 부분이 문제가 되는지 예시를 통해 알아봅시다. 함수 내부에 `let userName`라는 변수가 있으면 이 지역변수는 압축기에 의해 `let a` 등(짧은 이름)으로 대체되는데, 이때 `userName` 모두가 `a`로 교체됩니다. `userName`은 지역변수이고, 함수 외부에선 함수 내부에 있는 변수에 접근할 수 없기 때문에 이렇게 해도 전혀 문제가 없죠. 압축기는 단순히 변수를 찾아서 바꾸지 않고 코드 구조를 분석해 기존에 작성한 코드의 기능을 망가뜨리지 않으면서 영리하게 제 역할을 수행합니다. -======= -For instance, if a function has `let userName`, minifier replaces it with `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function, minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, so they don't break anything. They're not just a dumb find-and-replace. ->>>>>>> upstream/master +구체적으로 어떤 부분이 문제가 되는지 예시를 통해 알아봅시다. 함수 내부에 `let userName`라는 변수가 있으면 이 지역변수는 압축기에 의해 `let a` 등(해당 글자가 이미 사용 중이라면 다른 짧은 이름)으로 대체되는데, 이때 `userName` 모두가 `a`로 교체됩니다. `userName`은 지역변수이고, 함수 외부에선 함수 내부에 있는 변수에 접근할 수 없기 때문에 이렇게 해도 전혀 문제가 없죠. 압축기는 단순히 찾아바꾸기가 아니라 코드 구조를 분석해 기존 코드의 기능을 망가뜨리지 않으면서 영리하게 제 역할을 수행합니다. 이런 동작 방식 때문에 `new Function` 문법으로 만든 함수 내부에서 외부 변수에 접근하려고 하면 `userName`은 이미 이름이 변경되었기 때문에 찾을 수 없게 됩니다. diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md index 4a89ab268e..41967d1fe9 100644 --- a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md +++ b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md @@ -27,11 +27,7 @@ let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...) : 실행 전 대기 시간으로, 단위는 밀리초(millisecond, 1000밀리초 = 1초)이며 기본값은 0입니다. `arg1`, `arg2`... -<<<<<<< HEAD -: 함수에 전달할 인수들로, IE9 이하에선 지원하지 않습니다. -======= -: Arguments for the function ->>>>>>> upstream/master +: 함수에 전달할 인수입니다. 예시를 통해 `setTimeout`을 어떻게 쓸 수 있는지 알아봅시다. 아래 코드를 실행하면 1초 후에 `sayHi()`가 호출됩니다. @@ -106,11 +102,7 @@ alert(timerId); // 위 타이머 식별자와 동일함 (취소 후에도 식별 다시 한번 말씀드리자면, 스케줄링에 관한 명세는 따로 존재하지 않습니다. 명세가 없기 때문에 호스트 환경마다 약간의 차이가 있을 수밖에 없습니다. -<<<<<<< HEAD -참고로 브라우저는 HTML5의 [timers section](https://www.w3.org/TR/html5/webappapis.html#timers)을 준수하고 있습니다. -======= -For browsers, timers are described in the [timers section](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers) of HTML Living Standard. ->>>>>>> upstream/master +참고로 브라우저는 HTML Living Standard의 [timers section](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers)을 준수하고 있습니다. ## setInterval @@ -137,11 +129,7 @@ setTimeout(() => { clearInterval(timerId); alert('정지'); }, 5000); ```smart header="`alert` 창이 떠 있더라도 타이머는 멈추지 않습니다." Chrome과 Firefox를 포함한 대부분의 브라우저는 `alert/confirm/prompt` 창이 떠 있는 동안에도 내부 타이머를 멈추지 않습니다. -<<<<<<< HEAD 위 예시를 실행하고 첫 번째 `alert` 창이 떴을 때 몇 초간 기다렸다가 창을 닫으면, 두 번째 `alert` 창이 바로 나타나는 것을 보고 이를 확인할 수 있습니다. 이런 이유로 얼럿 창은 명시한 지연 시간인 2초보다 더 짧은 간격으로 뜨게 됩니다. -======= -So if you run the code above and don't dismiss the `alert` window for some time, then the next `alert` will be shown immediately as you do it. The actual interval between alerts will be shorter than 2 seconds. ->>>>>>> upstream/master ``` ## 중첩 setTimeout @@ -230,11 +218,7 @@ setTimeout(function run() { ![](settimeout-interval.svg) -<<<<<<< HEAD -**중첩 `setTimeout`을 사용하면 명시한 지연(여기서는 100ms)이 보장됩니다.** -======= -**The nested `setTimeout` ensures a minimum delay (100ms here) between the end of one call and the beginning of the subsequent one.** ->>>>>>> upstream/master +**중첩 `setTimeout`을 사용하면 이전 호출이 끝난 후 다음 호출이 시작되기까지 명시한 지연(여기서는 100ms)이 보장됩니다.** 이렇게 지연 간격이 보장되는 이유는 이전 함수의 실행이 종료된 이후에 다음 함수 호출에 대한 계획이 세워지기 때문입니다. @@ -248,11 +232,7 @@ setTimeout(function() {...}, 100); `setInterval`의 경우는, `clearInterval`이 호출되기 전까지 함수에 대한 참조가 메모리에 유지됩니다. -<<<<<<< HEAD 그런데 이런 동작 방식에는 부작용이 하나 있습니다. 외부 렉시컬 환경을 참조하는 함수가 있다고 가정해 봅시다. 이 함수가 메모리에 남아있는 동안엔 외부 변수 역시 메모리에 남아있기 마련입니다. 그런데 이렇게 되면 실제 함수가 차지했어야 하는 공간보다 더 많은 메모리 공간이 사용됩니다. 이런 부작용을 방지하고 싶다면 스케줄링할 필요가 없어진 함수는 아무리 작더라도 취소하도록 합시다. -======= -There's a side effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function anymore, it's better to cancel it, even if it's very small. ->>>>>>> upstream/master ```` ## 대기 시간이 0인 setTimeout @@ -275,13 +255,8 @@ alert("Hello"); 대기 시간이 0인 setTimeout을 활용한 브라우저 환경에서의 유스 케이스는 에서 자세히 다루도록 하겠습니다. -<<<<<<< HEAD -````smart header="브라우저 환경에서 실제 대기 시간은 0이 아닙니다." -브라우저는 [HTML5 표준](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers)에서 정한 중첩 타이머 실행 간격 관련 제약을 준수합니다. 해당 표준엔 "다섯 번째 중첩 타이머 이후엔 대기 시간을 최소 4밀리초 이상으로 강제해야 한다."라는 제약이 명시되어있습니다. -======= -````smart header="Zero delay is in fact not zero (in a browser)" -In the browser, there's a limitation of how often nested timers can run. The [HTML Living Standard](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers) says: "after five nested timers, the interval is forced to be at least 4 milliseconds.". ->>>>>>> upstream/master +````smart header="실제로 지연시간이 0인 경우는 없습니다(브라우저 환경)." +브라우저는 [HTML Living Standard](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers)에서 정한 중첩 타이머 실행 간격 관련 제약을 준수합니다. 해당 표준엔 "다섯 번째 중첩 타이머 이후엔 대기 시간을 최소 4밀리초 이상으로 강제해야 한다."라는 제약을 명시합니다. 예시를 보며 이 제약 사항을 이해해봅시다. 예시 내 `setTimeout`은 지연 없이 함수 run을 다시 호출할 수 있게 스케줄링 되어 있습니다. 배열 `times`에는 실제 지연 간격에 대한 정보가 기록되도록 해놓았는데, 배열 times에 어떤 값이 저장되는지 알아봅시다. @@ -306,41 +281,22 @@ setTimeout(function run() { 이는 오래전부터 있던 제약인데, 구식 스크립트 중 일부는 아직 이 제약에 의존하는 경우가 있어서 명세서를 변경하지 못하고 있는 상황입니다. -<<<<<<< HEAD -한편, 서버 측엔 이런 제약이 없습니다. Node.js의 [process.nextTick](https://nodejs.org/api/process.html)과 [setImmediate](https://nodejs.org/api/timers.html)를 이용하면 비동기 작업을 지연 없이 실행할 수 있습니다. 위에서 언급된 제약은 브라우저에 한정됩니다. -======= -For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [setImmediate](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args) for Node.js. So this note is browser-specific. ->>>>>>> upstream/master +한편, 서버 측엔 이런 제약이 없습니다. Node.js의 [setImmediate](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args)와 같은 방법으로 비동기 작업을 즉시 실행할 수 있습니다. 위에서 언급된 제약은 브라우저에 한정합니다. ```` ## 요약 -<<<<<<< HEAD - `setInterval(func, delay, ...args)`과 `setTimeout(func, delay, ...args)`은 `delay`밀리초 후에 `func`을 규칙적으로, 또는 한번 실행하도록 해줍니다. -- `setInterval·setTimeout`을 호출하고 반환받은 값을 `clearInterval·clearTimeout`에 넘겨주면 스케줄링을 취소할 수 있습니다. -- 중첩 `setTimeout`을 사용하면 `setInterval`을 사용한 것보다 유연하게 코드를 작성할 수 있습니다. 여기에 더하여 *지연 간격* 보장이라는 장점도 있습니다. +- `setTimeout·setInterval`을 호출하고 반환받은 값을 `clearTimeout·clearInterval`에 넘겨주면 스케줄링을 취소할 수 있습니다. +- 중첩 `setTimeout`을 사용하면 `setInterval`을 사용한 것보다 유연하게 코드를 작성할 수 있습니다. 여기에 더하여 실행 *사이의* 지연 간격을 더 정확하게 조절할 수 있게 해줍니다. - 대기 시간이 0인 setTimeout(`setTimeout(func, 0)` 혹은 `setTimeout(func)`)을 사용하면 '현재 스크립트의 실행이 완료된 후 가능한 한 빠르게' 원하는 함수를 호출할 수 있습니다. - 지연 없이 중첩 `setTimeout`을 5회 이상 호출하거나 지연 없는 `setInterval`에서 호출이 5회 이상 이뤄지면, 4밀리초 이상의 지연 간격이 강제로 더해집니다. 이는 브라우저에만 적용되는 사항이며, 하위 호환성을 위해 유지되고 있습니다. -======= -- Methods `setTimeout(func, delay, ...args)` and `setInterval(func, delay, ...args)` allow us to run the `func` once/regularly after `delay` milliseconds. -- To cancel the execution, we should call `clearTimeout/clearInterval` with the value returned by `setTimeout/setInterval`. -- Nested `setTimeout` calls are a more flexible alternative to `setInterval`, allowing us to set the time *between* executions more precisely. -- Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current script is complete". -- The browser limits the minimal delay for five or more nested calls of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons. ->>>>>>> upstream/master 스케줄링 메서드를 사용할 땐 명시한 지연 간격이 *보장*되지 않을 수도 있다는 점에 유의해야 합니다. -<<<<<<< HEAD -아래와 같은 상황에서 브라우저 내 타이머가 느려지면 지연 간격이 보장되지 않습니다. +아래와 같은 여러 이유로 브라우저 내 타이머가 느려질 수 있습니다. - CPU가 과부하 상태인 경우 - 브라우저 탭이 백그라운드 모드인 경우 -- 노트북이 배터리에 의존해서 구동 중인 경우 -======= -For example, the in-browser timer may slow down for a lot of reasons: -- The CPU is overloaded. -- The browser tab is in the background mode. -- The laptop is on battery saving mode. ->>>>>>> upstream/master +- 노트북이 배터리 절약 모드인 경우 이런 상황에서 타이머의 최소 지연 시간은 300밀리초에서 심하면 1,000밀리초까지 늘어납니다. 연장 시간은 브라우저나 구동 중인 운영 체제의 성능 설정에 따라 다릅니다. diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md index 8ed4537729..a64f3243ba 100644 --- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md +++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md @@ -36,19 +36,11 @@ function cachingDecorator(func) { slow = cachingDecorator(slow); -<<<<<<< HEAD -alert( slow(1) ); // slow(1)이 저장되었습니다. -alert( "다시 호출: " + slow(1) ); // 동일한 결과 - -alert( slow(2) ); // slow(2)가 저장되었습니다. -alert( "다시 호출: " + slow(2) ); // 윗줄과 동일한 결과 -======= -alert( slow(1) ); // slow(1) is cached and the result returned -alert( "Again: " + slow(1) ); // slow(1) result returned from cache - -alert( slow(2) ); // slow(2) is cached and the result returned -alert( "Again: " + slow(2) ); // slow(2) result returned from cache ->>>>>>> upstream/master +alert( slow(1) ); // slow(1)를 캐시에 저장하고 결과를 반환합니다. +alert( "다시 호출: " + slow(1) ); // 캐시에서 slow(1)의 결과를 가져옵니다. + +alert( slow(2) ); // slow(2)를 캐시에 저장하고 결과를 반환합니다. +alert( "다시 호출: " + slow(2) ); // 캐시에서 slow(2)의 결과를 가져옵니다. ``` `cachingDecorator`같이 인수로 받은 함수의 행동을 변경시켜주는 함수를 *데코레이터(decorator)* 라고 부릅니다. @@ -309,32 +301,18 @@ func.apply(context, args) 따라서 아래 코드 두 줄은 거의 같은 역할을 합니다. ```js -<<<<<<< HEAD -func.call(context, ...args); // 전개 구문을 사용해 인수가 담긴 배열을 전달하는 것과 -func.apply(context, args); // call을 사용하는 것은 동일합니다. -``` - -그런데 약간의 차이가 있긴 합니다. -======= func.call(context, ...args); func.apply(context, args); ``` -They perform the same call of `func` with given context and arguments. +위 코드는 `func`을 동일한 컨텍스트와 인수로 호출합니다. -There's only a subtle difference regarding `args`: ->>>>>>> upstream/master +그런데 `args`에 관해 약간의 차이가 있긴 합니다. - 전개 구문 `...`은 *이터러블* `args`을 분해 해 `call`에 전달할 수 있도록 해줍니다. - `apply`는 오직 *유사 배열* 형태의 `args`만 받습니다. -<<<<<<< HEAD -이 차이만 빼면 두 메서드는 완전히 동일하게 동작합니다. 인수가 이터러블 형태라면 `call`을, 유사 배열 형태라면 `apply`를 사용하면 됩니다. - 배열같이 이터러블이면서 유사 배열인 객체엔 둘 다를 사용할 수 있는데, 대부분의 자바스크립트 엔진은 내부에서 `apply`를 최적화 하기 때문에 `apply`를 사용하는 게 좀 더 빠르긴 합니다. -======= -...And for objects that are both iterable and array-like, such as a real array, we can use any of them, but `apply` will probably be faster, because most JavaScript engines internally optimize it better. ->>>>>>> upstream/master 이렇게 컨텍스트와 함께 인수 전체를 다른 함수에 전달하는 것을 *콜 포워딩(call forwarding)* 이라고 합니다. diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md index c5e53cb141..8372c465a7 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md @@ -1,9 +1,5 @@ -<<<<<<< HEAD -에러는 `ask`가 함수 `loginOk`, `loginFail`을 객체 없이 가지고 오기 때문에 발생합니다. -======= -The error occurs because `askPassword` gets functions `loginOk/loginFail` without the object. ->>>>>>> upstream/master +에러는 `askPassword`가 함수 `loginOk`, `loginFail`을 객체 없이 가지고 오기 때문에 발생합니다. ask는 `loginOk`, `loginFail`을 호출할 때 `this=undefined`라고 자연스레 가정합니다. diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 9f56d635a1..760b6ee404 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -123,11 +123,7 @@ funcUser(); // John */!* ``` -<<<<<<< HEAD -여기서 `func.bind(user)`는 `func`의 `this`를 `user`로 '바인딩한 변형'이라고 생각하시면 됩니다. -======= -Here `func.bind(user)` is a "bound variant" of `func`, with fixed `this=user`. ->>>>>>> upstream/master +여기서 `func.bind(user)`는 `this=user`로 고정된 `func`의 '바인딩한 변형'이라고 생각하면 됩니다. 인수는 원본 함수 `func`에 '그대로' 전달됩니다. @@ -189,13 +185,8 @@ let user = { let say = user.say.bind(user); -<<<<<<< HEAD -say("Hello"); // Hello, John (인수 "Hello"가 say로 전달되었습니다.) -say("Bye"); // Bye, John ("Bye"가 say로 전달되었습니다.) -======= -say("Hello"); // Hello, John! ("Hello" argument is passed to say) -say("Bye"); // Bye, John! ("Bye" is passed to say) ->>>>>>> upstream/master +say("Hello"); // Hello, John! (인수 "Hello"를 say에 전달합니다.) +say("Bye"); // Bye, John! ("Bye"를 say에 전달합니다.) ``` ````smart header="`bindAll`로 메서드 전체 바인딩하기" @@ -209,11 +200,7 @@ for (let key in user) { } ``` -<<<<<<< HEAD -자바스크립트 라이브러리를 사용해도 대규모 바인딩을 할 수 있습니다. lodash 라이브러리의 [_.bindAll(object, methodNames)](http://lodash.com/docs#bindAll)이 그 예입니다. -======= -JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(object, methodNames)](https://lodash.com/docs#bindAll) in lodash. ->>>>>>> upstream/master +자바스크립트 라이브러리를 사용해도 대규모 바인딩을 할 수 있습니다. lodash 라이브러리의 [_.bindAll(object, methodNames)](https://lodash.com/docs#bindAll)이 그 예입니다. ```` ## 부분 적용 @@ -258,11 +245,7 @@ alert( double(5) ); // = mul(2, 5) = 10 이런 방식을 [부분 적용(partial application)](https://en.wikipedia.org/wiki/Partial_application)이라고 부릅니다. 부분 적용을 사용하면 기존 함수의 매개변수를 고정하여 새로운 함수를 만들 수 있습니다. -<<<<<<< HEAD -위 예시에선 `this`를 사용하지 않았다는 점에 주목하시기 바랍니다. `bind`엔 컨텍스트를 항상 넘겨줘야 하므로 `null`을 사용했습니다. -======= -Please note that we actually don't use `this` here. But `bind` requires it, so we must put in something like `null`. ->>>>>>> upstream/master +위 예시에선 `this`를 사용하지 않았다는 점에 주목합니다. 그런데 `bind`는 컨텍스트가 필요하므로 `null` 같은 값을 넣어줘야 합니다. 부분 적용을 사용해 3을 곱해주는 함수 `triple`을 만들어보겠습니다. diff --git a/1-js/06-advanced-functions/12-arrow-functions/article.md b/1-js/06-advanced-functions/12-arrow-functions/article.md index 5b1709cf0f..e159ee3742 100644 --- a/1-js/06-advanced-functions/12-arrow-functions/article.md +++ b/1-js/06-advanced-functions/12-arrow-functions/article.md @@ -51,13 +51,8 @@ let group = { showList() { *!* this.students.forEach(function(student) { -<<<<<<< HEAD - // TypeError: Cannot read property 'title' of undefined - alert(this.title + ': ' + student) -======= // Error: Cannot read property 'title' of undefined alert(this.title + ': ' + student); ->>>>>>> upstream/master }); */!* } diff --git a/1-js/07-object-properties/01-property-descriptors/article.md b/1-js/07-object-properties/01-property-descriptors/article.md index 11c94b67cb..d4ce5f8061 100644 --- a/1-js/07-object-properties/01-property-descriptors/article.md +++ b/1-js/07-object-properties/01-property-descriptors/article.md @@ -19,11 +19,7 @@ 자 이제 본격적으로 프로퍼티 플래그에 대해 다뤄봅시다. 먼저 플래그를 얻는 방법을 알아보겠습니다. -<<<<<<< HEAD -[Object.getOwnPropertyDescriptor](mdn:js/Object/getOwnPropertyDescriptor)메서드를 사용하면 특정 프로퍼티에 대한 정보를 *모두* 얻을 수 있습니다. -======= -The method [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) allows to query the *full* information about a property. ->>>>>>> upstream/master +[Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) 메서드를 사용하면 특정 프로퍼티에 대한 정보를 *모두* 얻을 수 있습니다. 문법: ```js @@ -58,11 +54,7 @@ alert( JSON.stringify(descriptor, null, 2 ) ); */ ``` -<<<<<<< HEAD -메서드 [Object.defineProperty](mdn:js/Object/defineProperty)를 사용하면 플래그를 변경할 수 있습니다. -======= -To change the flags, we can use [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). ->>>>>>> upstream/master +메서드 [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty)를 사용하면 플래그를 변경할 수 있습니다. 문법: @@ -128,13 +120,8 @@ user.name = "Pete"; // Error: Cannot assign to read only property 'name' 이제 `defineProperty`를 사용해 `writable` 플래그를 `true`로 변경하지 않는 한 그 누구도 객체의 이름을 변경할 수 없게 되었습니다. -<<<<<<< HEAD ```smart header="에러는 엄격 모드에서만 발생합니다." -비 엄격 모드에선 읽기 전용 프로퍼티에 값을 쓰려고 해도 에러가 발생하지 않습니다. 다만 이때 값을 변경하는 것은 불가능합니다. 비 엄격 모드에선 이와 같이 플래그에서 정한 규칙을 위반하는 행위는 에러 없이 그냥 무시됩니다. -======= -```smart header="Errors appear only in strict mode" -In non-strict mode, no errors occur when writing to non-writable properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict. ->>>>>>> upstream/master +비 엄격 모드에선 쓰기 불가 프로퍼티 등에 값을 써도 에러가 발생하지 않습니다. 다만 이때 값을 변경하는 것은 불가능합니다. 비 엄격 모드에선 이와 같이 플래그에서 정한 규칙을 위반하는 행위는 에러 없이 그냥 무시됩니다. ``` 아래 예시는 위 예시와 동일하게 동작합니다. 다만 아래 예시에선 `defineProperty` 메서드를 사용해 프로퍼티를 밑바닥부터 만들어 보았습니다. @@ -205,11 +192,7 @@ alert(Object.keys(user)); // name 구성 가능하지 않음을 나타내는 플래그(non-configurable flag)인 `configurable:false`는 몇몇 내장 객체나 프로퍼티에 기본으로 설정되어있습니다. -<<<<<<< HEAD -어떤 프로퍼티의 `configurable` 플래그가 `false`로 설정되어 있다면 해당 프로퍼티는 객체에서 지울 수 없습니다. -======= -A non-configurable property can't be deleted, its attributes can't be modified. ->>>>>>> upstream/master +구성 가능하지 않은(non-configurable) 프로퍼티는 객체에서 삭제할 수 없고, 속성도 수정할 수 없습니다. 내장 객체 `Math`의 `PI` 프로퍼티가 대표적인 예입니다. 이 프로퍼티는 쓰기와 열거, 구성이 불가능합니다. @@ -234,32 +217,20 @@ Math.PI = 3; // Error, because it has writable: false // 수정도 불가능하지만 지우는 것 역시 불가능합니다. ``` -<<<<<<< HEAD -`configurable` 플래그를 `false`로 설정하면 돌이킬 방법이 없습니다. `defineProperty`를 써도 값을 `true`로 되돌릴 수 없죠. - -`configurable:false`가 만들어내는 구체적인 제약사항은 아래와 같습니다. -1. `configurable` 플래그를 수정할 수 없음 -2. `enumerable` 플래그를 수정할 수 없음. -3. `writable: false`의 값을 `true`로 바꿀 수 없음(`true`를 `false`로 변경하는 것은 가능함). -4. 접근자 프로퍼티 `get/set`을 변경할 수 없음(새롭게 만드는 것은 가능함). - -이런 특징을 이용하면 아래와 같이 "영원히 변경할 수 없는" 프로퍼티(`user.name`)를 만들 수 있습니다. -======= -We also can't change `Math.PI` to be `writable` again: ->>>>>>> upstream/master +`Math.PI`를 다시 `writable`로 바꾸는 것도 불가능합니다. ```js run // Error, because of configurable: false Object.defineProperty(Math, "PI", { writable: true }); ``` -There's absolutely nothing we can do with `Math.PI`. +`Math.PI`로는 아무것도 할 수 없습니다. -Making a property non-configurable is a one-way road. We cannot change it back with `defineProperty`. +프로퍼티를 구성 가능하지 않은 상태로 만들면 되돌릴 수 없습니다. `defineProperty`를 사용해도 다시 구성 가능하게 만들 수 없습니다. -**Please note: `configurable: false` prevents changes of property flags and its deletion, while allowing to change its value.** +**참고: `configurable: false`는 프로퍼티 플래그 변경과 삭제를 막지만, 값 변경은 허용합니다.** -Here `user.name` is non-configurable, but we can still change it (as it's writable): +아래 예시에서 `user.name`은 구성 가능하지 않은 프로퍼티지만 writable이므로 값을 변경할 수 있습니다. ```js run let user = { @@ -274,7 +245,7 @@ user.name = "Pete"; // works fine delete user.name; // Error ``` -And here we make `user.name` a "forever sealed" constant, just like the built-in `Math.PI`: +아래 예시에서는 내장 객체 `Math.PI`처럼 `user.name`을 "변경할 수 없는" 상수로 만듭니다. ```js run let user = { @@ -286,43 +257,22 @@ Object.defineProperty(user, "name", { configurable: false }); -<<<<<<< HEAD -*!* -// user.name 프로퍼티의 값이나 플래그를 변경할 수 없습니다. -// 아래와 같이 변경하려고 하면 에러가 발생합니다. -// user.name = "Pete" -// delete user.name -// Object.defineProperty(user, "name", { value: "Pete" }) -Object.defineProperty(user, "name", {writable: true}); // Error -*/!* -``` - -```smart header="\"non-configurable\"은 \"non-writable\"과 다릅니다." -`configurable` 플래그가 `false`이더라도 `writable` 플래그가 `true`이면 프로퍼티 값을 변경할 수 있습니다. - -`configurable: false`는 플래그 값 변경이나 프로퍼티 삭제를 막기 위해 만들어졌지, 프로퍼티 값 변경을 막기 위해 만들어진 게 아닙니다. -======= -// won't be able to change user.name or its flags -// all this won't work: +// user.name과 플래그를 변경할 수 없습니다. +// 아래는 모두 동작하지 않습니다. user.name = "Pete"; delete user.name; Object.defineProperty(user, "name", { value: "Pete" }); ``` -```smart header="The only attribute change possible: writable true -> false" -There's a minor exception about changing flags. +```smart header="가능한 플래그 변경: writable true -> false" +플래그 변경에는 한 가지 예외가 있습니다. -We can change `writable: true` to `false` for a non-configurable property, thus preventing its value modification (to add another layer of protection). Not the other way around though. ->>>>>>> upstream/master +구성 가능하지 않은 프로퍼티라도 `writable: true`를 `false`로 변경할 수 있습니다. 이렇게 하면 값 변경을 막을 수 있습니다. 반대로 false를 true로 변경하는 것은 불가능합니다. ``` ## Object.defineProperties -<<<<<<< HEAD -[Object.defineProperties(obj, descriptors)](mdn:js/Object/defineProperties) 메서드를 사용하면 프로퍼티 여러 개를 한 번에 정의할 수 있습니다. -======= -There's a method [Object.defineProperties(obj, descriptors)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) that allows to define many properties at once. ->>>>>>> upstream/master +[Object.defineProperties(obj, descriptors)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) 메서드를 사용하면 프로퍼티 여러 개를 한 번에 정의할 수 있습니다. 문법: @@ -348,11 +298,7 @@ Object.defineProperties(user, { ## Object.getOwnPropertyDescriptors -<<<<<<< HEAD -[Object.getOwnPropertyDescriptors(obj)](mdn:js/Object/getOwnPropertyDescriptors) 메서드를 사용하면 프로퍼티 설명자를 전부 한꺼번에 가져올 수 있습니다. -======= -To get all property descriptors at once, we can use the method [Object.getOwnPropertyDescriptors(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors). ->>>>>>> upstream/master +[Object.getOwnPropertyDescriptors(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors) 메서드를 사용하면 프로퍼티 설명자를 한꺼번에 가져올 수 있습니다. 이 메서드를 `Object.defineProperties`와 함께 사용하면 객체 복사 시 플래그도 함께 복사할 수 있습니다. @@ -370,11 +316,7 @@ for (let key in user) { 그런데 이 방법은 플래그는 복사하지 않습니다. 플래그 정보도 복사하려면 `Object.defineProperties`를 사용하시기 바랍니다. -<<<<<<< HEAD -위 샘플 코드처럼 `for..in`을 사용해 객체를 복사하면 심볼형 프로퍼티도 놓치게 됩니다. 하지만 `Object.getOwnPropertyDescriptors`는 심볼형 프로퍼티를 포함한 프로퍼티 설명자 *전체*를 반환합니다. -======= -Another difference is that `for..in` ignores symbolic and non-enumerable properties, but `Object.getOwnPropertyDescriptors` returns *all* property descriptors including symbolic and non-enumerable ones. ->>>>>>> upstream/master +또 다른 점은 `for..in`은 심볼형 프로퍼티와 열거가 불가능한 프로퍼티를 무시합니다. 하지만 `Object.getOwnPropertyDescriptors`는 심볼형 프로퍼티와 열거가 불가능한 프로퍼티를 포함한 프로퍼티 설명자 *전체*를 반환합니다. ## 객체 수정을 막아주는 다양한 메서드 @@ -382,46 +324,24 @@ Another difference is that `for..in` ignores symbolic and non-enumerable propert 아래 메서드를 사용하면 한 객체 내 프로퍼티 *전체*를 대상으로 하는 제약사항을 만들 수 있습니다. -<<<<<<< HEAD -[Object.preventExtensions(obj)](mdn:js/Object/preventExtensions) -: 객체에 새로운 프로퍼티를 추가할 수 없게 합니다. - -[Object.seal(obj)](mdn:js/Object/seal) -: 새로운 프로퍼티 추가나 기존 프로퍼티 삭제를 막아줍니다. 프로퍼티 전체에 `configurable: false`를 설정하는 것과 동일한 효과입니다. - -[Object.freeze(obj)](mdn:js/Object/freeze) -: 새로운 프로퍼티 추가나 기존 프로퍼티 삭제, 수정을 막아줍니다. 프로퍼티 전체에 `configurable: false, writable: false`를 설정하는 것과 동일한 효과입니다. -======= [Object.preventExtensions(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions) -: Forbids the addition of new properties to the object. +: 객체에 새로운 프로퍼티를 추가할 수 없게 합니다. [Object.seal(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal) -: Forbids adding/removing of properties. Sets `configurable: false` for all existing properties. +: 새로운 프로퍼티 추가나 기존 프로퍼티 삭제를 막아줍니다. 기존 프로퍼티 전체에 `configurable: false`를 설정합니다. [Object.freeze(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) -: Forbids adding/removing/changing of properties. Sets `configurable: false, writable: false` for all existing properties. ->>>>>>> upstream/master +: 새로운 프로퍼티 추가나 기존 프로퍼티 삭제, 수정을 막아줍니다. 기존 프로퍼티 전체에 `configurable: false, writable: false`를 설정합니다. 아래 메서드는 위 세 가지 메서드를 사용해서 설정한 제약사항을 확인할 때 사용할 수 있습니다. -<<<<<<< HEAD -[Object.isExtensible(obj)](mdn:js/Object/isExtensible) -: 새로운 프로퍼티를 추가하는 게 불가능한 경우 `false`를, 그렇지 않은 경우 `true`를 반환합니다. - -[Object.isSealed(obj)](mdn:js/Object/isSealed) -: 프로퍼티 추가, 삭제가 불가능하고 모든 프로퍼티가 `configurable: false`이면 `true`를 반환합니다. - -[Object.isFrozen(obj)](mdn:js/Object/isFrozen) -: 프로퍼티 추가, 삭제, 변경이 불가능하고 모든 프로퍼티가 `configurable: false, writable: false`이면 `true`를 반환합니다. -======= [Object.isExtensible(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible) -: Returns `false` if adding properties is forbidden, otherwise `true`. +: 새로운 프로퍼티를 추가하는 게 불가능한 경우 `false`를, 그렇지 않은 경우 `true`를 반환합니다. [Object.isSealed(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed) -: Returns `true` if adding/removing properties is forbidden, and all existing properties have `configurable: false`. +: 프로퍼티 추가, 삭제가 불가능하고 모든 프로퍼티가 `configurable: false`이면 `true`를 반환합니다. [Object.isFrozen(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen) -: Returns `true` if adding/removing/changing properties is forbidden, and all current properties are `configurable: false, writable: false`. ->>>>>>> upstream/master +: 프로퍼티 추가, 삭제, 변경이 불가능하고 모든 프로퍼티가 `configurable: false, writable: false`이면 `true`를 반환합니다. 위 메서드들은 실무에선 잘 사용되지 않습니다. diff --git a/1-js/07-object-properties/02-property-accessors/article.md b/1-js/07-object-properties/02-property-accessors/article.md index 2899bea100..a150831247 100644 --- a/1-js/07-object-properties/02-property-accessors/article.md +++ b/1-js/07-object-properties/02-property-accessors/article.md @@ -5,11 +5,7 @@ 첫 번째 종류는 *데이터 프로퍼티(data property)* 입니다. 지금까지 사용한 모든 프로퍼티는 데이터 프로퍼티입니다. 데이터 프로퍼티 조작 방법에 대해선 모두 알고 계실 것이라 생각합니다. -<<<<<<< HEAD 두 번째는 *접근자 프로퍼티(accessor property)* 라 불리는 새로운 종류의 프로퍼티입니다. 접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)하고 설정(set)하는 역할을 담당합니다. 그런데 외부 코드에서는 함수가 아닌 일반적인 프로퍼티처럼 보입니다. -======= -The second type of property is something new. It's an *accessor property*. They are essentially functions that execute on getting and setting a value, but look like regular properties to an external code. ->>>>>>> upstream/master ## getter와 setter