diff --git a/1-js/06-advanced-functions/06-function-object/article.md b/1-js/06-advanced-functions/06-function-object/article.md index 39ba9160dd..37839779c5 100644 --- a/1-js/06-advanced-functions/06-function-object/article.md +++ b/1-js/06-advanced-functions/06-function-object/article.md @@ -153,7 +153,7 @@ alert( `Called ${sayHi.counter} times` ); // Called 2 times ```warn header="A property is not a variable" A property assigned to a function like `sayHi.counter = 0` does *not* define a local variable `counter` inside it. In other words, a property `counter` and a variable `let counter` are two unrelated things. -We can treat a function as an object, store properties in it, but that has no effect on its execution. Variables are not function properties and vice versa. These are just parallel worlds. +We can treat a function as an object, store properties in it, but that has no effect on its execution. Variables never use function properties and vice versa. These are just parallel worlds. ``` Function properties can replace closures sometimes. For instance, we can rewrite the counter function example from the chapter <info:closure> to use a function property: @@ -340,7 +340,7 @@ Functions are objects. Here we covered their properties: -- `name` -- the function name. Usually taken from the function definition, but if there's non, JavaScript tries to guess it from the context (e.g. an assignment). +- `name` -- the function name. Exists not only when given in the function definition, but also for assignments and object properties. - `length` -- the number of arguments in the function definition. Rest parameters are not counted. If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called a Named Function Expression. The name can be used inside to reference itself, for recursive calls or such. diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 06e2000ff1..6720a6d50d 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -3,17 +3,17 @@ libs: --- -# Function binding +# 함수 바인딩(Function binding) -When using `setTimeout` with object methods or passing object methods along, there's a known problem: "losing `this`". +자바스크립트에서 `setTimeout`을 사용해서 객체 메서드 또는 객체 메서드를 통해서 보낼 때, "`this`를 잃어버리는" 잘 알려진 문제점이 있습니다. -Suddenly, `this` just stops working right. The situation is typical for novice developers, but happens with experienced ones as well. +갑자기 `this`가 작동 안 하게 되는 것이죠. 이 상황은 초보 개발자에게 자주 일어나지만, 모두가 경험하는 문제입니다. -## Losing "this" +## "this"를 잃어버리는 것 -We already know that in JavaScript it's easy to lose `this`. Once a method is passed somewhere separately from the object -- `this` is lost. +자바스크립트는 `this`를 쉽게 잃어버린다는 것을 배웠습니다. 어떠한 매서드가 객체로부터 독립적으로 넘겨질 때 `this`를 잃어버립니다. -Here's how it may happen with `setTimeout`: +아래 예시를 통해 그 현상이 `setTimeout`에서 어떻게 일어나는지 살펴보겠습니다. ```js run let user = { @@ -28,22 +28,22 @@ setTimeout(user.sayHi, 1000); // Hello, undefined! */!* ``` -As we can see, the output shows not "John" as `this.firstName`, but `undefined`! +위에 예시처럼, 결과는 "John"이 `this.firstName` 이 되어야 하는데 `undefined` 입니다! -That's because `setTimeout` got the function `user.sayHi`, separately from the object. The last line can be rewritten as: +그 이유는 `setTimeout` 이 `user.sayHi`함수를 객체로부터 독립적으로 가져왔기 때문입니다. 마지막 라인을 다시 쓰면 다음과 같습니다. ```js let f = user.sayHi; -setTimeout(f, 1000); // lost user context +setTimeout(f, 1000); // user 컨텍스트를 잃어버렸음 ``` -The method `setTimeout` in-browser is a little special: it sets `this=window` for the function call (for Node.js, `this` becomes the timer object, but doesn't really matter here). So for `this.firstName` it tries to get `window.firstName`, which does not exist. In other similar cases as we'll see, usually `this` just becomes `undefined`. +`setTimeout` 매서드는 브라우저 안에서는 조금 특별하게 작동합니다. 함수를 호출하기 위해서 `this=window` 를 설정합니다. (Node.js 에서는 `this` 가 타이머 객체가 되기 때문에 Node.js 에서는 크게 상관은 없습니다). 그래서 `this.firstName` 은 존재하지 않는 `window.firstName`을 가져오려고 합니다. 이러한 이유로, `this`가 `undefined`로 되는 것을 자주 볼 수 있습니다. -The task is quite typical -- we want to pass an object method somewhere else (here -- to the scheduler) where it will be called. How to make sure that it will be called in the right context? +호출될 곳에서 객체 메서드를 다른 곳으로 (여기서는 스케줄러에) 전달하려고 하는 것은 매우 전형적인 현상입니다. 어떻게 하면 올바른 컨텍스트에서 호출되는 것을 확인할 수 있을까요? -## Solution 1: a wrapper +## 첫 번째 해결책: a wrapper -The simplest solution is to use a wrapping function: +가장 간단한 해결방법은 wrapping 함수를 사용하는 것입니다. ```js run let user = { @@ -60,17 +60,17 @@ setTimeout(function() { */!* ``` -Now it works, because it receives `user` from the outer lexical environment, and then calls the method normally. +위의 예시는 작동합니다, 왜냐하면 `user`를 외부 렉시컬 환경으로 받아서 메서드를 보통 때처럼 호출했기 때문입니다. -The same, but shorter: +위 예시와 같지만, 짧게 하면 아래와 같습니다. ```js setTimeout(() => user.sayHi(), 1000); // Hello, John! ``` -Looks fine, but a slight vulnerability appears in our code structure. +위의 코드는 보기에는 괜찮지만, 코드 구조에는 약간 취약한 점이 있습니다. -What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, it will call the wrong object! +`setTimeout`이 시작되기 전에 (1초의 지연이 있습니다!) `user`가 값을 변경하면 어떻게 될까요? 그렇게 되면 갑자기 잘못된 개체를 호출할 것입니다! ```js run @@ -83,30 +83,30 @@ let user = { setTimeout(() => user.sayHi(), 1000); -// ...within 1 second +// ...1초 안에 user = { sayHi() { alert("Another user in setTimeout!"); } }; -// Another user in setTimeout?!? +// setTimeout에 또 다른 user 가?!? ``` -The next solution guarantees that such thing won't happen. +두 번째 해결방법은 갑자기 값이 변경되는 현상이 일어나는 걸 방지합니다. -## Solution 2: bind +## 두 번째 해결방법: bind -Functions provide a built-in method [bind](mdn:js/Function/bind) that allows to fix `this`. +함수들은 `this`를 수정하도록 하는 내장 매서드 [bind](mdn:js/Function/bind) 를 제공합니다. -The basic syntax is: +기본 문법: ```js -// more complex syntax will be little later +// 더 복잡한 문법은 나중에 다루겠습니다 let boundFunc = func.bind(context); -``` +```` -The result of `func.bind(context)` is a special function-like "exotic object", that is callable as function and transparently passes the call to `func` setting `this=context`. +`func.bind(context)`의 결과는 "exotic object" 같은 특별한 함수입니다, 이것은 함수로서 호출할 수도 있으면서 `func`에 `this = context`를 명확하게 전달합니다. -In other words, calling `boundFunc` is like `func` with fixed `this`. +즉,`boundFunc`를 호출하는 것은 `this`가 고정된 `func`와 같습니다. -For instance, here `funcUser` passes a call to `func` with `this=user`: +아래 예시에서 `funcUser`는 `this = user`를 가지고 `func` 를 호출합니다. ```js run let user = { @@ -123,9 +123,9 @@ funcUser(); // John */!* ``` -Here `func.bind(user)` as a "bound variant" of `func`, with fixed `this=user`. +위의 예시에서 `func.bind (user)`는`func`의 "바운드 변수"로 고정된 `this = user`를 가지고 있습니다. -All arguments are passed to the original `func` "as is", for instance: +모든 인수는 기본적으로 "있는 그대로" `func` 에 전달됩니다. 예시는 아래와 같습니다: ```js run let user = { @@ -140,11 +140,11 @@ function func(phrase) { let funcUser = func.bind(user); *!* -funcUser("Hello"); // Hello, John (argument "Hello" is passed, and this=user) +funcUser("Hello"); // Hello, John ("Hello" 인수가 넘겨졌고 this=user입니다) */!* ``` -Now let's try with an object method: +이제 아래 예시에서 객체 메서드를 사용해 보겠습니다. ```js run @@ -164,9 +164,9 @@ sayHi(); // Hello, John! setTimeout(sayHi, 1000); // Hello, John! ``` -In the line `(*)` we take the method `user.sayHi` and bind it to `user`. The `sayHi` is a "bound" function, that can be called alone or passed to `setTimeout` -- doesn't matter, the context will be right. +`(*)`줄에서 `user.sayHi` 메소드를 가져와서 `user`에 바인드합니다. `sayHi`는 단독으로 호출되거나 `setTimeout`에 전달될 수 있는 "바운드 (bound)"함수입니다 - 컨텍스트는 맞기 때문에 중요하지는 않습니다. -Here we can see that arguments are passed "as is", only `this` is fixed by `bind`: +인수는 "있는 그대로" 전달되고, 단지 "this"만이 `bind`에 의해 고정된다는 것을 알 수 있습니다. ```js run let user = { @@ -178,12 +178,12 @@ let user = { let say = user.say.bind(user); -say("Hello"); // Hello, John ("Hello" argument is passed to say) -say("Bye"); // Bye, John ("Bye" is passed to say) +say("Hello"); // Hello, John ("Hello"인수가 say로 넘겨졌음) +say("Bye"); // Bye, John ("Bye"가 say 로 넘겨졌음) ``` ````smart header="Convenience method: `bindAll`" -If an object has many methods and we plan to actively pass it around, then we could bind them all in a loop: +객체가 많은 메서드를 가지고 있고 그것을 능동적으로 전달할 계획이라면, 모든 것을 루프로 묶을 수 있습니다. ```js for (let key in user) { @@ -193,11 +193,11 @@ for (let key in user) { } ``` -JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(obj)](http://lodash.com/docs#bindAll) in lodash. +자바스크립트 라이브러리들은 편리한 매스 바인딩(mass binding) 함수들을 제공하고 있습니다. lodash를 예로 들면 [_.bindAll(obj)](http://lodash.com/docs#bindAll) 가 있습니다. ```` -## Summary +## 요약 -Method `func.bind(context, ...args)` returns a "bound variant" of function `func` that fixes the context `this` and first arguments if given. +메서드`func.bind (context, ... args)`는 컨텍스트의 `this`와 첫 번째 인수가 주어지면 수정되는 `func` 함수의 "바운드 변수"를 반환합니다. -Usually we apply `bind` to fix `this` in an object method, so that we can pass it somewhere. For example, to `setTimeout`. There are more reasons to `bind` in the modern development, we'll meet them later. +보통 객체의 메서드에서 `this` 를 고치기 위해 `bind`를 사용하면 값을 전달할 수 있습니다. 예제에서 `setTimeout`같은 메서드를 살펴보았습니다. 현대적인 개발에 'bind'를 사용하는 이유는 더 있지만, 나중에 다시 다루어 보겠습니다.