diff --git a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md index 0177c8f6e7..c035ab9b25 100644 --- a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md +++ b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md @@ -2,14 +2,14 @@ importance: 5 --- -# Set and decrease for counter +# 카운터를 설정하고 감소시키기 -Modify the code of `makeCounter()` so that the counter can also decrease and set the number: +`makeCounter()` 함수를 수정해서 카운터가 숫자를 감소시키고 설정하게 해보세요. -- `counter()` should return the next number (as before). -- `counter.set(value)` should set the `count` to `value`. -- `counter.decrease()` should decrease the `count` by 1. +- `counter()` 다음 숫자를 반환합니다. (이전의 것처럼) +- `counter.set(value)` `count` 를 `value` 로 설정합니다. +- `counter.decrease()` `count`를 1 감소시킵니다. -See the sandbox code for the complete usage example. +샌드박스의 코드를 완성된 예제로 참고하세요. -P.S. You can use either a closure or the function property to keep the current count. Or write both variants. +P.S. 클로져나 함수프로퍼티를 사용해서 현재 count 값을 유지해도 됩니다. 또는 두 방법을 모두 사용해도 됩니다. diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md index dc13f260b9..f98f796ca0 100644 --- a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md @@ -2,9 +2,9 @@ importance: 2 --- -# Sum with an arbitrary amount of brackets +# 정해지지않은 괄호의 양을 합산하기 -Write function `sum` that would work like this: +다음과 같이 작동하는 `sum` 함수를 작성해보세요. ```js sum(1)(2) == 3; // 1 + 2 @@ -14,4 +14,4 @@ sum(6)(-1)(-2)(-3) == 0 sum(0)(1)(2)(3)(4)(5) == 15 ``` -P.S. Hint: you may need to setup custom object to primitive conversion for your function. \ No newline at end of file +P.S. 힌트: 아마도 특수 객체(custom object)를 활용해서 원시값 변환에 사용하세요. \ No newline at end of file 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 37839779c5..e8df165148 100644 --- a/1-js/06-advanced-functions/06-function-object/article.md +++ b/1-js/06-advanced-functions/06-function-object/article.md @@ -1,20 +1,20 @@ -# Function object, NFE +# 함수 객체, NFE -As we already know, functions in JavaScript are values. +자바스크립트에서 함수는 values(값) 이라는 것을 알고 있습니다. -Every value in JavaScript has a type. What type is a function? +자바스크립트의 모든 values는 타입을 가지고 있습니다. 함수의 타입은 무엇일까요? -In JavaScript, functions are objects. +자바스크립트에서 함수는 객체입니다. -A good way to imagine functions is as callable "action objects". We can not only call them, but also treat them as objects: add/remove properties, pass by reference etc. +좋은 의미에서 함수들이 호출할 수 있는 "행동하는 객체"라고 상상해 보세요. 호출하기만 하는 것이 아니라 함수를 객체처럼 다루어야 합니다. -## The "name" property +## "name" 프로퍼티 -Function objects contain a few useable properties. +함수 객체들은 몇 가지 사용 가능한 프로퍼티를 가지고 있습니다. -For instance, a function's name is accessible as the "name" property: +예를 들면 함수의 이름은 접근 가능한 "name"이라는 프로퍼티입니다. ```js run function sayHi() { @@ -24,7 +24,7 @@ function sayHi() { alert(sayHi.name); // sayHi ``` -What's more funny, the name-assigning logic is smart. It also assigns the correct name to functions that are used in assignments: +재밌는 건 이름을 할당하는 로직은 똑똑하다는 것입니다. assignments를 사용해서 함수의 이름을 할당해도 제대로 작동합니다. ```js run let sayHi = function() { @@ -34,7 +34,7 @@ let sayHi = function() { alert(sayHi.name); // sayHi (works!) ``` -It also works if the assignment is done via a default value: +default value를 사용해도 마찬가지로 작동합니다. ```js run function f(sayHi = function() {}) { @@ -44,9 +44,9 @@ function f(sayHi = function() {}) { f(); ``` -In the specification, this feature is called a "contextual name". If the function does not provide one, then in an assignment it is figured out from the context. +자바스크립트 규격에 따르면, 이러한 기능을 "contextual name"이라고 합니다. 만약에 함수가 이것을 제공하지 않으면 할당할 때 컨텍스트에서 가져옵니다. -Object methods have names too: +객체 메서드들도 이름들을 가지고 있습니다. ```js run let user = { @@ -65,21 +65,21 @@ alert(user.sayHi.name); // sayHi alert(user.sayBye.name); // sayBye ``` -There's no magic though. There are cases when there's no way to figure out the right name. In that case, the name property is empty, like here: +몇 가지 경우에는 올바른 이름을 지정해 줄 수 없는 경우도 있습니다. 이런 몇몇 경우에는 name 프로퍼티는 비어있습니다. 아래와 같이 ```js -// function created inside array +// 배열안에서 함수가 생성됨 let arr = [function() {}]; -alert( arr[0].name ); // -// the engine has no way to set up the right name, so there is none +alert( arr[0].name ); // <빈 문자열> +// 엔진이 이름을 설정할 방법이 없으므로 존재하지 않음 ``` -In practice, however, most functions do have a name. +실제로는 거의 모든 함수는 name을 가지고 있습니다. -## The "length" property +## "length" 프로퍼티 -There is another built-in property "length" that returns the number of function parameters, for instance: +또 다른 내부 프로퍼티인 "length"는 함수 매개변수의 개수를 반환합니다. 예를 들면 ```js run function f1(a) {} @@ -91,20 +91,20 @@ alert(f2.length); // 2 alert(many.length); // 2 ``` -Here we can see that rest parameters are not counted. +여기서 나머지 매개변수는 적용받지 않습니다. -The `length` property is sometimes used for introspection in functions that operate on other functions. +가끔 `length` 프로퍼티는 다른 함수들 안에서 동작하는 함수들의 내부검사에 사용됩니다. -For instance, in the code below the `ask` function accepts a `question` to ask and an arbitrary number of `handler` functions to call. +예를 들면 아래의 `ask` 코드의 함수는 `question` 을 받아서 물어보고 `handler`의 임의의수의 함수들을 호출합니다. -Once a user provides their answer, the function calls the handlers. We can pass two kinds of handlers: +사용자가 답을 제공했을 때 함수는 핸들러들을 호출해서 두 가지 종류로 전달합니다. -- A zero-argument function, which is only called when the user gives a positive answer. -- A function with arguments, which is called in either case and returns an answer. +- 오직 사용자가 올바른 답을 제시해야만 호출되는 인수가 없는 함수. +- 어떤 경우에도 답을 반환하는 매개변수가 있는 함수 -The idea is that we have a simple, no-arguments handler syntax for positive cases (most frequent variant), but are able to provide universal handlers as well. +아이디어는 간단합니다. 인수가 없는 핸들러 구문은 긍정적인 경우에만(대부분의 경우), 다른하나는 다목적인 핸들러도 제공하기 위함입니다. -To call `handlers` the right way, we examine the `length` property: +`handlers` 를 바르게 호출하기 위해서는 `length` 프로퍼티를 검사해야 합니다. ```js run function ask(question, ...handlers) { @@ -120,25 +120,25 @@ function ask(question, ...handlers) { } -// for positive answer, both handlers are called -// for negative answer, only the second one +// 정수의경우 두가지 핸들러 모두 호출 +// 음수의 경우, 두번재것만 호출 ask("Question?", () => alert('You said yes'), result => alert(result)); ``` -This is a particular case of so-called [polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) -- treating arguments differently depending on their type or, in our case depending on the `length`. The idea does have a use in JavaScript libraries. +위와 같이 특별한 경우를 [다형성(polymorphism)](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) 이라고 부릅니다 -- 인수를 타입이나, 예제의 경우에는 `length`에 따라 다르게 다루는 경우입니다. 이러한 방법은 자바스크립트 라이브러리에서 사용됩니다. -## Custom properties +## 특수 프로퍼티들 -We can also add properties of our own. +또한 자체적으로 만든 프로퍼티도 추가할 수 있습니다. -Here we add the `counter` property to track the total calls count: +다음 예제는 `counter` 프로퍼티를 추가해 몇 번 호출되었는지 추적합니다. ```js run function sayHi() { alert("Hi"); *!* - // let's count how many times we run + // 몇 번 동작하는지 세어봅니다 sayHi.counter++; */!* } @@ -147,20 +147,20 @@ sayHi.counter = 0; // initial value sayHi(); // Hi sayHi(); // Hi -alert( `Called ${sayHi.counter} times` ); // Called 2 times +alert( `Called ${sayHi.counter} times` ); // 2번 호출되었습니다 ``` -```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. +```warn header="프로퍼티는 변수가 아닙니다" +프로퍼티가 `sayHi.counter = 0` 같은 함수에 명시되었을 때 지역변수 `counter` 로 존재하는 것은 *아닙니다*. 다른 말로 하면, `counter` 프로퍼티와 변수 `let counter` 는 관계가 없습니다. -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 to use a function property: +가끔 함수 프로퍼티들은 클로져(Closures)들을 대체할 수 있습니다. 예를 들면, 챕터에 있는 카운터 함수의 예를 함수 프로퍼티를 사용하는 방법으로 다시 작성할 수 있습니다. ```js run function makeCounter() { - // instead of: + // 다음과 같이 하는 대신에 // let count = 0 function counter() { @@ -177,11 +177,11 @@ alert( counter() ); // 0 alert( counter() ); // 1 ``` -The `count` is now stored in the function directly, not in its outer Lexical Environment. +여기서 `count`는 외부 렉시컬 환경이 아니라 함수에 바로 저장되어 있습니다. -Is it better or worse than using a closure? +클로져(closure)를 사용하는 것보다 좋은 방법일까요? 아닐까요? -The main difference is that if the value of `count` lives in an outer variable, then external code is unable to access it. Only nested functions may modify it. And if it's bound to a function, then such a thing is possible: +가장 다른 점은, 만약 `count`의 value가 외부수에 존재한다면 외부코드에서는 접근할 수 없다는 것입니다. 오직 중첩함수만이 수정할 수 있을 것입니다. 그리고 만약 그것이 함수에 연결되돼있는 상황이라면 그때는 외부에서도 접근이 가능할 것입니다. ```js run function makeCounter() { @@ -203,13 +203,13 @@ alert( counter() ); // 10 */!* ``` -So the choice of implementation depends on our aims. +그렇다면 구현하는 방법의 선택은 목적에 따라 다를 것입니다. -## Named Function Expression +## NFE(명시된 함수 표현 식) -Named Function Expression, or NFE, is a term for Function Expressions that have a name. +명시된 함수 표현 식 또는 NFE란 이름을 가진 함수표현 식을 뜻하는 용어입니다. -For instance, let's take an ordinary Function Expression: +일반적인 함수표현 식을 예로 들어보겠습니다. ```js let sayHi = function(who) { @@ -217,7 +217,7 @@ let sayHi = function(who) { }; ``` -And add a name to it: +그리고 여기에 이름을 붙여보겠습니다. ```js let sayHi = function *!*func*/!*(who) { @@ -225,13 +225,13 @@ let sayHi = function *!*func*/!*(who) { }; ``` -Did we achieve anything here? What's the purpose of that additional `"func"` name? +여기서 무언가 얻은 게 있을까요? `"func"`이름을 붙이는 목적은 무엇일까요? -First let's note, that we still have a Function Expression. Adding the name `"func"` after `function` did not make it a Function Declaration, because it is still created as a part of an assignment expression. +첫 번째로 함수표현 식을 사용합니다. `"func"`이름을 `function`다음에 붙이는 것은 함수를 정의하지는 않습니다. 왜냐하면 여전히 대입 표현형식의 한 부분이기 때문이죠. -Adding such a name also did not break anything. +이름을 추가하는 것이 무언가를 망가뜨리지도 않았습니다. -The function is still available as `sayHi()`: +함수는 아직도 `sayHi()`로 사용 가능하죠. ```js run let sayHi = function *!*func*/!*(who) { @@ -241,12 +241,12 @@ let sayHi = function *!*func*/!*(who) { sayHi("John"); // Hello, John ``` -There are two special things about the name `func`: +`func`이름에는 두 가지 특별한 점이 있습니다: -1. It allows the function to reference itself internally. -2. It is not visible outside of the function. +1. 그것은 함수에 내부적으로 자신을 레퍼런스합니다. +2. 그것은 함수 외부에서 보이지 않습니다. -For instance, the function `sayHi` below calls itself again with `"Guest"` if no `who` is provided: +예를 들어, 함수 `sayHi` 아래에서 `who`가 주어지지 않았을 때 자신을 `"Guest"` 로 부르면 ```js run let sayHi = function *!*func*/!*(who) { @@ -254,21 +254,21 @@ let sayHi = function *!*func*/!*(who) { alert(`Hello, ${who}`); } else { *!* - func("Guest"); // use func to re-call itself + func("Guest"); // func를 사용해서 스스로를 호출 합니다. */!* } }; sayHi(); // Hello, Guest -// But this won't work: -func(); // Error, func is not defined (not visible outside of the function) +// 그러나 이건 동작하지 않습니다. +func(); // 에러 func 는 정의되지 않았습니다. (함수 밖에서는 보이지 않습니다) ``` -Why do we use `func`? Maybe just use `sayHi` for the nested call? +`func`를 사용하는 사람이 있나요? 아마도 중첩함수를 부를 때는 `sayHi`를 사용하지 않습니까? -Actually, in most cases we can: +사실 대부분의 경우 ```js let sayHi = function(who) { @@ -282,7 +282,7 @@ let sayHi = function(who) { }; ``` -The problem with that code is that the value of `sayHi` may change. The function may go to another variable, and the code will start to give errors: +위의 코드의 문제점은 `sayHi`의 value가 바뀔 수 있다는 것입니다. 아마도 함수는 다른 변숫값으로 갈 수 있고 코드가 동작한다면 에러를 출력할 것입니다. ```js run let sayHi = function(who) { @@ -290,7 +290,7 @@ let sayHi = function(who) { alert(`Hello, ${who}`); } else { *!* - sayHi("Guest"); // Error: sayHi is not a function + sayHi("Guest"); // 에러 sayHi 는 함수가 아님 */!* } }; @@ -298,14 +298,14 @@ let sayHi = function(who) { let welcome = sayHi; sayHi = null; -welcome(); // Error, the nested sayHi call doesn't work any more! +welcome(); // 에러 중첩된 sayHi는 더 이상 작동하지 않습니다! ``` -That happens because the function takes `sayHi` from its outer lexical environment. There's no local `sayHi`, so the outer variable is used. And at the moment of the call that outer `sayHi` is `null`. +이런 현상이 일어나는 것은 `sayHi` 함수를 외부 렉시컬 환경에서 가져오기 때문입니다. 지역적으로(local) `sayHi` 는 없습니다. 그래서 외부변수가 사용된 것입니다. 외부의 `sayHi`를 호출하면 `null`인 것입니다. -The optional name which we can put into the Function Expression is meant to solve exactly these kinds of problems. +함수 표현식에 이름을 붙이는 것은 정확히 이러한 문제를 해결합니다. -Let's use it to fix our code: +다음 코드를 수정해 봅시다. ```js run let sayHi = function *!*func*/!*(who) { @@ -313,7 +313,7 @@ let sayHi = function *!*func*/!*(who) { alert(`Hello, ${who}`); } else { *!* - func("Guest"); // Now all fine + func("Guest"); // 지금은 괜찮습니다 */!* } }; @@ -321,32 +321,32 @@ let sayHi = function *!*func*/!*(who) { let welcome = sayHi; sayHi = null; -welcome(); // Hello, Guest (nested call works) +welcome(); // Hello, Guest (중첩함수가 작동합니다) ``` -Now it works, because the name `"func"` is function-local. It is not taken from outside (and not visible there). The specification guarantees that it will always reference the current function. +`"func"`가 함수의 내부(function-local)이기 때문에 지금은 작동합니다. 그건 밖에서 가져온 value가 아닙니다(그리고 밖에선 보이지도 않습니다). 규격에 의하면 항상 현재 함수를 레퍼런스합니다. -The outer code still has it's variable `sayHi` or `welcome`. And `func` is an "internal function name", how the function can call itself internally. +외부코드는 아직도 `sayHi` 또는 `welcome` 변수를 가지고 있습니다. 그리고 `func` 이 내부 함수 이름입니다. 어떻게 함수가 자신을 내부에서 부를 수 있을까요. -```smart header="There's no such thing for Function Declaration" -The "internal name" feature described here is only available for Function Expressions, not to Function Declarations. For Function Declarations, there's just no syntax possibility to add a one more "internal" name. +```smart header="함수 선언과는 관련이 없습니다" +"내부 이름" 기능은 함수 선언가 아니라 오직 함수 표현 식에서만 가능합니다. 함수를 정의할 때는 내부 이름을 명시할 문법은 존재하지 않습니다. -Sometimes, when we need a reliable internal name, it's the reason to rewrite a Function Declaration to Named Function Expression form. +가끔, 내부이름이 필요할 때 함수 선언를 명시된 함수 표현 식으로 다시 작성할 뿐입니다. ``` -## Summary +## 요약 -Functions are objects. +함수는 객체이다. -Here we covered their properties: +다음 함수 프로퍼티들에 대해 알아보았습니다. -- `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. +- `name` -- 함수의 이름. 함수를 정의할 때만 명시할 수 있는 게 아니 assignments와 객체 프로퍼티로도 가능하다. +- `length` -- 함수 선언에 있는 인수들의 수. 나머지 연산자들은 세지 않는다. -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. +만약 함수가 함수 표현 식으로 되었다면(not in the main code flow), 그리고 그것이 이름을 가진다면 그것은 명시된(이름을 가진) 함수 표현형식이다. 그 이름은 내부에서 재귀적인 호출 같은 레퍼런스 용도로 사용될 수 있다. -Also, functions may carry additional properties. Many well-known JavaScript libraries make great use of this feature. +또한 함수들은 추가적인 프로퍼티를 가질 수 있다. 자바스크립트에서 많이 알려진 라이브러리들은 이러한 특징을 훌륭하게 사용하고 있다. -They create a "main" function and attach many other "helper" functions to it. For instance, the [jquery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts. +라이브러리들은 "main" 함수를 생성하고 다른 많은 "helper" 함수를 붙인다. 예를 들면 [jQuery](https://jquery.com) 라이브러리는 함수의 이름을 `$`라고 붙였다. [lodash](https://lodash.com) 라이브러리는 `_`이라는 이름을 붙였다. 그리고 거기에 `_.clone`, `_.keyBy` 같은 함수를 만들었으며 그것들을 배우기 위한 다른 프로퍼티들도 있다. ([docs](https://lodash.com/docs) 참고) 사실, 그것들은 전역 지역에 오염을 막기 위한 것입니다. 그래서 하나의 라이브러리는 오직 하나의 전역 변수를 제공하죠. 혹시 일어날 수 있는 이름 충돌을 방지하는 것입니다. -So, a function can do a useful job by itself and also carry a bunch of other functionality in properties. +그래서 함수는 스스로 유용한 작업을 행할 수도 있고 다른 여러 기능을 프로퍼티에 가지고 있을 수 있는 것입니다. 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 e0750e3218..8818ab73fe 100644 --- a/1-js/06-advanced-functions/07-new-function/article.md +++ b/1-js/06-advanced-functions/07-new-function/article.md @@ -1,19 +1,19 @@ -# The "new Function" syntax +# "새로운 함수" 문법 -There's one more way to create a function. It's rarely used, but sometimes there's no alternative. +함수를 생성하는데 한 가지 방법이 더 있습니다. 제한적으로 사용되지만, 가끔 이 방법 외에는 대안이 없을 때도 있죠. -## Syntax +## 문법 -The syntax for creating a function: +함수를 만드는 문법은 다음과 같습니다. ```js let func = new Function ([arg1[, arg2[, ...argN]],] functionBody) ``` -In other words, function parameters (or, more precisely, names for them) go first, and the body is last. All arguments are strings. +다른 말로 하면, 함수의 매개 변수(또는 정확히는 그것들의 이름)가 먼저 오고, 본문이 마지막에 따라옵니다. 모든 인수는 문자열입니다. -It's easier to understand by looking at an example. Here's a function with two arguments: +더 쉽게 이해하기 위해서 함수와 두 개의 인수가 있는 예제를 보겠습니다. ```js run let sum = new Function('a', 'b', 'return a + b'); @@ -21,7 +21,7 @@ let sum = new Function('a', 'b', 'return a + b'); alert( sum(1, 2) ); // 3 ``` -If there are no arguments, then there's only a single argument, the function body: +만약에 인수들이 없다면 오직 하나의 함수 본문을 가진 인수만이 있습니다. ```js run let sayHi = new Function('alert("Hello")'); @@ -29,11 +29,11 @@ let sayHi = new Function('alert("Hello")'); sayHi(); // Hello ``` -The major difference from other ways we've seen is that the function is created literally from a string, that is passed at run time. +가장 다른 점은 함수가 문자 그대로 실행될 때 넘겨진다는 것입니다. -All previous declarations required us, programmers, to write the function code in the script. +예전의 모든 선언문에서 함수의 코드는 스크립트 안에서 쓰였습니다. -But `new Function` allows to turn any string into a function. For example, we can receive a new function from a server and then execute it: +그러나 `new Function` 이라는 문법은 어떠한 문자열을 함수로 바꾸어주는 역활을 합니다. 예를 들면, 새로운 함수를 서버로 받아서 실행해야 할 때처럼입니다. ```js let str = ... receive the code from a server dynamically ... @@ -42,13 +42,13 @@ let func = new Function(str); func(); ``` -It is used in very specific cases, like when we receive code from a server, or to dynamically compile a function from a template. The need for that usually arises at advanced stages of development. +이것은 굉장히 특정한 상황에만 사용됩니다. 서버로부터 코드를 받아올 때나 아니면 템블릿으로 부터 함수를 유동적으로 컴파일 할 때 입니다. 이런 것들이 필요할 때는 좀 더 고급스러운 개발단계가 필요할 때 입니다. -## Closure +## 클로져(Closure) -Usually, a function remembers where it was born in the special property `[[Environment]]`. It references the Lexical Environment from where it's created. +보통 함수는 어디에서 작성되었는지에 관한 특수한 프로퍼티는 `[[Environment]]`에 기억합니다. 생성된 렉시컬 환경을 참고합니다. -But when a function is created using `new Function`, its `[[Environment]]` references not the current Lexical Environment, but instead the global one. +그러나 `new Function`문을 사용해서 함수가 생성되면 `[[Environment]]`은 현재의 렉시컬 환경이 아닙니다. 대신에 전역(global)이 됩니다. ```js run @@ -62,10 +62,10 @@ function getFunc() { return func; } -getFunc()(); // error: value is not defined +getFunc()(); // 에러 값이 정의되지 않음 ``` -Compare it with the regular behavior: +일반적인 것과 비교해보세요. ```js run function getFunc() { @@ -81,27 +81,27 @@ function getFunc() { getFunc()(); // *!*"test"*/!*, from the Lexical Environment of getFunc ``` -This special feature of `new Function` looks strange, but appears very useful in practice. +특수한 기능인 `new Function`이 이상해 보일 수 있습니다만 아주 유용할 때가 있습니다. -Imagine that we must create a function from a string. The code of that function is not known at the time of writing the script (that's why we don't use regular functions), but will be known in the process of execution. We may receive it from the server or from another source. +문자열로부터 함수를 만들어야 하는 상황이 있어야 한다고 생각해보면. 그 함수의 코드는 스크립트를 작성할 때는 알 수 없습니다. (그래서 보통 함수를 사용하지 않죠) 그러나, 실행되는 프로세스에서는 알 수 있습니다. 서버 또는 다른 출처로부터 받게 되겠지요. -Our new function needs to interact with the main script. +새로운 함수는 메인 스크립트와 상호작용해야 할 것입니다. -Perhaps we want it to be able to access outer local variables? +그런데 혹시 그렇게 생성된 함수가 외부의 지역변수에 접근해야 한다면 어떨까요? -The problem is that before JavaScript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones. +문제는 자바스크립트가 운영에 반영되기 직전에 있습니다. 자바스크립트는 *minifier*라는 특수한 프로그램에 의해 압축된다는 것입니다 -- 코드의 특수한 주석이나 빈칸 -- 더 중요한 건 이것이 지역변수를 짧은 것으로 바꾸게 됩니다. -For instance, if a function has `let userName`, minifier replaces it `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. +예를 들면, 만약에 함수가 `let userName` 이라는 걸 가지고 있다면 minifier 는 그것은 `let a`로 (또는 그것을 어딘가 사용하고 있다면 다른 문자로) 대체합니다. 그리고 이런 일은 모든 곳에서 일어납니다. 보통 이런 작업은 값들이 지역변수라 안전하지만, 외부 함수에서는 여기에 접근할 수 없습니다. 그리고 함수의 내부에서 minifier는 언급된 모든 곳을 수정합니다. Minifiers 는 똑똑하고 코드의 구조를 분석하기 때문에 어떠한 곳도 망가뜨리진 않습니다. 그냥 무조건 찾아서 바꾸는 작업을 하는 건 아닙니다. -But, if `new Function` could access outer variables, then it would be unable to find `userName`, since this is passed in as a string *after* the code is minified. +그러나 만약 `new Function` 구문이 외부 변수들에 접근한다면 `userName` 이라는 것은 찾을 수 없을 것입니다. *이후의* 코드는 minified 되었기 때문이죠. -**Even if we could access outer lexical environment in `new Function`, we would have problems with minifiers.** +**`new Function`문법이 외부 렉시컬 환경에 접근할 수 있었을지라도 minifiers에 의한 문제는 생길 수 있습니다.** -The "special feature" of `new Function` saves us from mistakes. +`new Function`의 특별한 기능이 이런 실수로부터 예방합니다. -And it enforces better code. If we need to pass something to a function created by `new Function`, we should pass it explicitly as an argument. +그리고 좀더 좋은 코드를 제공합니다. `new Function`이란 문법을 사용한 함수에 무언가를 넘기려고 한다면 명시적으로 인수(argument)로 넘기는것이 좋습니다. -Our "sum" function actually does that right: +아래의 "sum"함수는 그것을 잘 표현하고 있습니다. ```js run *!* @@ -111,27 +111,27 @@ let sum = new Function('a', 'b', 'return a + b'); let a = 1, b = 2; *!* -// outer values are passed as arguments +// 필요한 값들이 매개변수로 전달되었음 alert( sum(a, b) ); // 3 */!* ``` -## Summary +## 요약 -The syntax: +문법 ```js let func = new Function(arg1, arg2, ..., body); ``` -For historical reasons, arguments can also be given as a comma-separated list. +역사적인 이유로 인수들은 콤바로 구별된 리스트로 사용할 수 있습니다. -These three mean the same: +다음 세가지 표현은 똑같습니다. ```js -new Function('a', 'b', 'return a + b'); // basic syntax -new Function('a,b', 'return a + b'); // comma-separated -new Function('a , b', 'return a + b'); // comma-separated with spaces +new Function('a', 'b', 'return a + b'); // 기본 문법 +new Function('a,b', 'return a + b'); // 콤마로 구별된 +new Function('a , b', 'return a + b'); // 콤마와 스페이스로 구별된 ``` -Functions created with `new Function`, have `[[Environment]]` referencing the global Lexical Environment, not the outer one. Hence, they cannot use outer variables. But that's actually good, because it saves us from errors. Passing parameters explicitly is a much better method architecturally and causes no problems with minifiers. +`new Function`으로 생성된 함수는 전역 렉시컬환경을 참조하는 `[[Environment]]`를 가지고 있습니다. 그러므로 그 함수는 외부 변수를 사용할 수 없습니다. 이것은 사실 에러를 방지하므로 좋은 현상입니다. 명시적으로 매개변수로 넘기는 것이 설계적으로 더 좋은 방법이고 minifiers와 문제가 생기지 않는 방법이기 때문입니다. diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md b/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md index 667c8ffa6f..ebf6df6796 100644 --- a/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md +++ b/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md @@ -2,26 +2,27 @@ importance: 5 --- -# What will setTimeout show? +# setTimeout 은 무엇을 보여줄까요? -In the code below there's a `setTimeout` call scheduled, then a heavy calculation is run, that takes more than 100ms to finish. +아래의 코드에는 `setTimeout` 호출이 스케줄되어 있고 무거운 계산이 실행됩니다. 끝내기 위해 100ms 이상 걸립니다. -When will the scheduled function run? +예정된 기능은 언제 실행될까요? -1. After the loop. -2. Before the loop. -3. In the beginning of the loop. +1. 반복문 후에. +2. 반복문 전에. +3. 반복문이 시작할 때. -What is `alert` going to show? +`alert`은 무엇을 보여줄까요? ```js let i = 0; setTimeout(() => alert(i), 100); // ? -// assume that the time to execute this function is >100ms +// 이 함수를 실행하는데 걸리는 시간이 100ms보다 크다고 가정합니다 for(let j = 0; j < 100000000; j++) { i++; } ``` + \ No newline at end of file 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 91310f3832..2e3b6d3c54 100644 --- a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md +++ b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md @@ -1,36 +1,36 @@ -# Scheduling: setTimeout and setInterval +# 스케줄링: setTimeout 과 setInterval -We may decide to execute a function not right now, but at a certain time later. That's called "scheduling a call". +함수를 지금 당장 실행하는 것이 아니라 나중에 실행해야 될 때가 있습니다. 이것을 "호출 스케줄링" 라고 합니다. -There are two methods for it: +이것을 구현하기 위한 두 가지 방법이 있습니다. -- `setTimeout` allows to run a function once after the interval of time. -- `setInterval` allows to run a function regularly with the interval between the runs. +- `setTimeout` 일정 시간이 지난 후에 함수를 실행합니다. +- `setInterval` 실행되고 일정 시간 동안 함수를 계속 실행합니다. -These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.js. +이런 방법들은 자바스크립트의 규격은 아닙니다만 거의 모든 환경들이 내부 스케줄러와 지원하는 매서드들을 가지고 있습니다. 특별히, 대부분의 브라우저와 Node.JS 에서 지원됩니다. ## setTimeout -The syntax: +문법: ```js let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...) ``` -Parameters: +매개변수: `func|code` -: Function or a string of code to execute. -Usually, that's a function. For historical reasons, a string of code can be passed, but that's not recommended. +: 함수 또는 코드 문자열이 실행됩니다. +보통은 이건 함수입니다. 역사적인 이유로 코드의 문자열로 넘겨질 수도 있지만 추천되는 방법은 아닙니다. `delay` -: The delay before run, in milliseconds (1000 ms = 1 second), by default 0. +: 실행하기 전에 밀리세컨드 단위로 딜레이를 줍니다. 기본값은 0입니다. `arg1`, `arg2`... -: Arguments for the function (not supported in IE9-) +: 함수의 인수들(IE9에서는 지원되지 않음). -For instance, this code calls `sayHi()` after one second: +예를 들면, 다음 코드는 1초 후에 `sayHi()` 를 호출합니다. ```js run function sayHi() { @@ -42,7 +42,7 @@ setTimeout(sayHi, 1000); */!* ``` -With arguments: +인수들의 사용: ```js run function sayHi(phrase, who) { @@ -54,90 +54,90 @@ setTimeout(sayHi, 1000, "Hello", "John"); // Hello, John */!* ``` -If the first argument is a string, then JavaScript creates a function from it. +만약에 첫 번째 인수가 문자이면 자바스크립트는 함수를 생성합니다. -So, this will also work: +그래서 다음과 같이 해도 작동하게 됩니다: ```js run no-beautify setTimeout("alert('Hello')", 1000); ``` -But using strings is not recommended, use functions instead of them, like this: +그러나 문자열들을 사용하는 건 추천하지 않습니다. 다음과 같이 함수를 사용하는 것이 더 좋습니다. ```js run no-beautify setTimeout(() => alert('Hello'), 1000); ``` -````smart header="Pass a function, but don't run it" -Novice developers sometimes make a mistake by adding brackets `()` after the function: +````smart header="함수는 넘기지만 실행하면 안 됩니다" +초보 개발자들은 때때로 함수 뒤에 `()` 을 붙이는 실수를 합니다: ```js -// wrong! +// 잘못된 코드! setTimeout(sayHi(), 1000); ``` -That doesn't work, because `setTimeout` expects a reference to function. And here `sayHi()` runs the function, and the *result of its execution* is passed to `setTimeout`. In our case the result of `sayHi()` is `undefined` (the function returns nothing), so nothing is scheduled. +`setTimeout` 가 함수를 참고하려고 하기 때문에 작동하지 않습니다. 그리고 여기서 `sayHi()`은 함수를 실행합니다.그런다음 *함수의 실행결과* 가 `setTimeout`으로 넘겨집니다. 이 경우에 `sayHi()`의 결과값은 `undefined` 입니다 (함수의 반환 값이 없기 때문에). 그래서 스케줄 되는 건 아무것도 없습니다. ```` -### Canceling with clearTimeout +### clearTimeout 로 취소하기 -A call to `setTimeout` returns a "timer identifier" `timerId` that we can use to cancel the execution. +`setTimeout` 을 실행하면 "timer identifier" 를 반환합니다. 실행단계에서 `timeId`를 사용해서 취소할 수 있습니다. -The syntax to cancel: +취소하기 위한 문법: ```js let timerId = setTimeout(...); clearTimeout(timerId); ``` -In the code below, we schedule the function and then cancel it (changed our mind). As a result, nothing happens: +아래의 코드처럼 함수를 스케줄하고 취소할 수 있습니다(마음이 바뀌었을 때). 결과적으로 아무 일도 일어나지 않습니다. ```js run no-beautify let timerId = setTimeout(() => alert("never happens"), 1000); alert(timerId); // timer identifier clearTimeout(timerId); -alert(timerId); // same identifier (doesn't become null after canceling) +alert(timerId); // 똑같은 identifier (취소후에 null 값이 되지 않음) ``` -As we can see from `alert` output, in a browser the timer identifier is a number. In other environments, this can be something else. For instance, Node.js returns a timer object with additional methods. +`alert`결과로 the timer identifier는 숫자라는 것을 알 수 있습니다. 다른 환경에서는 조금 다를 수 있습니다. 예를 들면, Node.js는 하나의 타이머 오브젝트를 추가적인 메서드들과 반환합니다. -Again, there is no universal specification for these methods, so that's fine. +그러나 다시 한번 얘기하자면 이러한 메서드들을 위한 보편적인 규격은 없습니다. -For browsers, timers are described in the [timers section](https://www.w3.org/TR/html5/webappapis.html#timers) of HTML5 standard. +브라우저의 경우 타이머들은 [timers section](https://www.w3.org/TR/html5/webappapis.html#timers) 에서 HTML5 기본으로 기술되어 있습니다. ## setInterval -The `setInterval` method has the same syntax as `setTimeout`: +`setInterval` 메서드는 `setTimeout`과 똑같은 문법을 가지고 있습니다. ```js let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) ``` -All arguments have the same meaning. But unlike `setTimeout` it runs the function not only once, but regularly after the given interval of time. +모든 변수는 똑같은 의미를 가지고 있습니다. 그라나 `setTimeout`은 함수를 단 한 번만 실행하지는 않는 대신, 주어진 일정 시간 동안 주기적으로 실행합니다. -To stop further calls, we should call `clearInterval(timerId)`. +호출된 것을 멈추려면 `clearInterval(timerId)`를 호출해야 합니다. -The following example will show the message every 2 seconds. After 5 seconds, the output is stopped: +다음 예제는 메시지를 2초마다 보여줍니다. 5초 후에는 정지됩니다. ```js run -// repeat with the interval of 2 seconds +// 2초간격으로 반복 let timerId = setInterval(() => alert('tick'), 2000); -// after 5 seconds stop +// 5초후에 정지 setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000); ``` -```smart header="Modal windows freeze time in Chrome/Opera/Safari" -In browsers IE and Firefox the internal timer continues "ticking" while showing `alert/confirm/prompt`, but in Chrome, Opera and Safari the internal timer becomes "frozen". +```smart header="크롬/오페라/사파리에서 모달 윈도는 시간을 정지시킵니다" +IE와 파이어폭스 브라우저의 내부 타이머는 `alert/confirm/prompt`를 보여주는 동안에도 틱 되고 있습니다. 그러나 크롬, 오페라, 사파리의 내부 타이머는 "정지" 됩니다. -So if you run the code above and don't dismiss the `alert` window for some time, then in Firefox/IE next `alert` will be shown immediately as you do it (2 seconds passed from the previous invocation), and in Chrome/Opera/Safari -- after 2 more seconds (timer did not tick during the `alert`). +그래서 위의 코드를 실행하고 `alert` 윈도를 바로 닫지 않으면 파이어폭스 / IE에서 경고가 즉시 표시됩니다.(이전 호출에서 2초가 경과 한) 크롬 / 오페라 / 사파리에서 - 2초 후에 (`alert` 중에는 타이머가 틱 되지 않음). ``` -## Recursive setTimeout +## 재귀적인 setTimeout -There are two ways of running something regularly. +주기적으로 실행하게 하는 방법에는 크게 2가지가 있습니다. -One is `setInterval`. The other one is a recursive `setTimeout`, like this: +하나는 `setInterval`이고 다른 하나는 `setTimeout`를 순회하는 것 입니다. 다음과 같습니다. ```js /** instead of: @@ -152,13 +152,13 @@ let timerId = setTimeout(function tick() { }, 2000); ``` -The `setTimeout` above schedules the next call right at the end of the current one `(*)`. +위에 있는 `setTimeout` 스케줄러는 현재 마지막에 있는 `(*)` 후에 다음 호출을 실행합니다. -The recursive `setTimeout` is a more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one. +회귀적인 `setTimeout` 방법은 `setInterval`보다 유동적입니다. 이 방법은 다음 호출이 다르게 스케줄되었을때 사용됩니다. 현재 결과에 달린 것이죠. -For instance, we need to write a service that sends a request to the server every 5 seconds asking for data, but in case the server is overloaded, it should increase the interval to 10, 20, 40 seconds... +예를 들면, 5초마다 데이터값을 얻기 위해 서버에 request를 보내는 서비스를 작성해야 한다고 할 때, 이때 서버는 오버로드 될 수 있고 이때는 시차를 10, 20, 40초로 증가시켜야 할 것입니다... -Here's the pseudocode: +여기에 의사 코드가 있습니다: ```js let delay = 5000; @@ -166,7 +166,7 @@ let timerId = setTimeout(function request() { ...send request... if (request failed due to server overload) { - // increase the interval to the next run + // 다음 실행 간격을 늘립니다 delay *= 2; } @@ -176,11 +176,11 @@ let timerId = setTimeout(function request() { ``` -And if we regularly have CPU-hungry tasks, then we can measure the time taken by the execution and plan the next call sooner or later. +만약 CPU를 많이 소모하는 작업이라면, 실행단계에서 소모되는 시간을 측정할 수 있고 그것에 따라 호출을 먼저 할지 나중에 할지 계획을 세울 수 있을 것입니다. -**Recursive `setTimeout` guarantees a delay between the executions, `setInterval` -- does not.** +**회귀적인 `setTimeout`은 다음 실행과의 사이에서 딜레이를 보장합니다. `setInterval`은 아닙니다.** -Let's compare two code fragments. The first one uses `setInterval`: +두 코드의 요소들을 비교해 보겠습니다. 첫 번째는 `setinterval`입니다: ```js let i = 1; @@ -189,7 +189,7 @@ setInterval(function() { }, 100); ``` -The second one uses recursive `setTimeout`: +두 번째는 재귀적인 `setTimeout`입니다: ```js let i = 1; @@ -199,52 +199,52 @@ setTimeout(function run() { }, 100); ``` -For `setInterval` the internal scheduler will run `func(i)` every 100ms: +`setInterval` 은 내부적인 스케줄러가 `func(i)`를 100ms마다 실행합니다: ![](setinterval-interval.png) -Did you notice? +알아차리셨나요? -**The real delay between `func` calls for `setInterval` is less than in the code!** +**`setInterval`을 위한 `func`를 호출할 때 실제 딜레이는 코드에 있는 것보다 짧습니다!** -That's normal, because the time taken by `func`'s execution "consumes" a part of the interval. +이건 정상입니다. 왜냐하면 `func`가 소모하는 시간은 내부적인 부분에서 실행단계가 "소모되는" 부분이기 때문입니다. -It is possible that `func`'s execution turns out to be longer than we expected and takes more than 100ms. +`func`의 실행이 예상하는 것보다 그리고 100ms보다 더 길어질 수도 있습니다. -In this case the engine waits for `func` to complete, then checks the scheduler and if the time is up, runs it again *immediately*. +이런 경우에는 엔진이 `func`이 끝날 때 까지 기다리고 스케줄러를 확인한 후에 시간이 다 되었으면 *바로* 다시 실행합니다. -In the edge case, if the function always executes longer than `delay` ms, then the calls will happen without a pause at all. +이런 특수한 경우에는, 함수는 항상 `delay`ms 보다 늦게 실행됩니다, 그리고는 호출들이 모든 것을 멈추지 않고 계속될 것입니다. -And here is the picture for the recursive `setTimeout`: +회귀적인 `setTimeout`에 대한 그림이 있습니다: ![](settimeout-interval.png) -**The recursive `setTimeout` guarantees the fixed delay (here 100ms).** +**회귀적인 `setTimeout`은 지정된 딜레이(여기서는 100ms)를 보장합니다** -That's because a new call is planned at the end of the previous one. +왜냐하면 새로운 호출이 계획될 때는 이전 것이 끝나는 곳이기 때문입니다. ````smart header="Garbage collection" -When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function from being garbage collected, even if there are no other references to it. +함수가 `setInterval/setTimeout`으로 넘겨졌을 때, 내부참고가 생성되고 스케줄러에 저장됩니다.그것에 다른 참조가 없을지라도 함수가 가비지 컬렉션 되는 것으로 부터 막아줍니다. ```js -// the function stays in memory until the scheduler calls it +// 다음 함수는 스케줄러가 호출할 때 까지 메모리에 상주합니다 setTimeout(function() {...}, 100); ``` -For `setInterval` the function stays in memory until `clearInterval` is called. +`setInterval` 함수는 `clearInterval` 함수가 호출되기 전까지 메모리에 머무릅니다. -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. +부작용은 있습니다. 함수가 외부 렉시컬 환경을 참조할 때, 그것이 살아있는 동안 외부 변수들도 살아있습니다.그것들은 함수 자신보다 많은 메모리를 잡아먹을 수 있습니다. 그래서 스케줄 된 함수가 더는 필요 없을 때는 그 함수가 아무리 작더라도 취소하는 게 좋습니다. ```` ## setTimeout(...,0) -There's a special use case: `setTimeout(func, 0)`, or just `setTimeout(func)`. +`setTimeout(func, 0)` 라는 특별한 사용 예가 있습니다. 또는 간단히 `setTimeout(func)`. -This schedules the execution of `func` as soon as possible. But scheduler will invoke it only after the current code is complete. +이 스케줄러는 `func`를 가능한 빨리 실행합니다. 그러나 스케줄러는 현재 코드가 완료됬을 때만 그것을 부를 것입니다. -So the function is scheduled to run "right after" the current code. In other words, *asynchronously*. +그래서 함수가 현재 코드가 "바로 끝나면" 실행되도록 스케줄 됩니다. 다른 말로 하면, *비동기적으로*. -For instance, this outputs "Hello", then immediately "World": +예를 들면, 다음 코드는 "World" 다음에 "Hello"를 바로 출력합니다: ```js run setTimeout(() => alert("World")); @@ -252,19 +252,19 @@ setTimeout(() => alert("World")); alert("Hello"); ``` -The first line "puts the call into calendar after 0ms". But the scheduler will only "check the calendar" after the current code is complete, so `"Hello"` is first, and `"World"` -- after it. +첫 번째 줄이 "달력에 0ms가 지난 후에 호출을 하도록 넣습니다". 그러나 스케줄러는 "예약 확인" 을 오직 현재 코드가 완료되어야만 진행할 것입니다. `"Hello"` 가 먼저 출력되고 `"World"` 가 그 다음입니다. -### Splitting CPU-hungry tasks +### CPU 를 많이 잡아먹는 작업을 나누기 -There's a trick to split CPU-hungry tasks using `setTimeout`. +`setTimeout`을 이용해서 CPU를 많이 잡아먹는 작업을 나누는 편법이 있습니다. -For instance, a syntax-highlighting script (used to colorize code examples on this page) is quite CPU-heavy. To highlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a big text that takes a lot. It may even cause the browser to "hang", which is unacceptable. +예를 들면, (이 페이지의 코드 예제에 색을 입히는 데 사용되는) 구문 강조 스크립트는 상당히 CPU 소모가 많습니다. 코드를 강조하기 위해서는 특별한 분석이 실행되고, 색칠된 요소들을 많이 생성한 후 문서에 추가합니다. -- 큰 문서의 경우 엄청나게 큰 작업입니다. 아마도 브라우저가 "멈추는" 받아 들일 수 없는 경우가 생길 수도 있습니다. -So we can split the long text into pieces. First 100 lines, then plan another 100 lines using `setTimeout(..., 0)`, and so on. +그래서 긴 문장은 쪼개는 것이 좋습니다. 첫 번째 100줄까지, 그리고는 다음 100줄을 `setTimeout(..., 0)`를 사용해서 나눕니다. 그리고 반복합니다. -For clarity, let's take a simpler example for consideration. We have a function to count from `1` to `1000000000`. +확실히 하기 위해, 간단한 예제를 보겠습니다. `1` 에서 `1000000000` 까지 세는 함수가 있습니다. -If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to click other buttons on the page -- you'll see that whole JavaScript actually is paused, no other actions work until it finishes. +이것을 실행하면 CPU는 멈출것입니다. 서버쪽 JS는 확실히 이것을 알아차릴 수 있습니다. 그리고 만약에 브라우저에서 이것을 실행하고 다른화면의 버튼을 클릭하려고 하면 -- 전체 자바스크립트가 중지된 것을 볼수 있으, 완료 될 때가지 다른 행동들은 동작하지 않습니다. ```js run let i = 0; @@ -273,7 +273,7 @@ let start = Date.now(); function count() { - // do a heavy job + // 무거운 작업을 진행 for (let j = 0; j < 1e9; j++) { i++; } @@ -284,9 +284,9 @@ function count() { count(); ``` -The browser may even show "the script takes too long" warning (but hopefully it won't, because the number is not very big). +브라우저는 아마도 "스크립트가 너무 오래 걸립니다"라는 경고를 보여줄지도 모릅니다. (그러나 숫자가 아주 크지는 않기 때문에, 아마도 아닐 것입니다). -Let's split the job using the nested `setTimeout`: +중첩된 `setTimeout`을 이용해서 나누어 보겠습니다: ```js run let i = 0; @@ -295,7 +295,7 @@ let start = Date.now(); function count() { - // do a piece of the heavy job (*) + // 무거운 작업중의 일부를 진행 (*) do { i++; } while (i % 1e6 != 0); @@ -303,7 +303,7 @@ function count() { if (i == 1e9) { alert("Done in " + (Date.now() - start) + 'ms'); } else { - setTimeout(count); // schedule the new call (**) + setTimeout(count); // 새로운 호출을 스케줄 (**) } } @@ -311,23 +311,23 @@ function count() { count(); ``` -Now the browser UI is fully functional during the "counting" process. +이제 브라우저 UI는 "숫자를 세는 동안에도" 완전히 작동합니다. -We do a part of the job `(*)`: +`(*)` 작업의 일부를 합니다: -1. First run: `i=1...1000000`. -2. Second run: `i=1000001..2000000`. -3. ...and so on, the `while` checks if `i` is evenly divided by `1000000`. +1. 첫번째 실행: `i=1...1000000`. +2. 두번째 실행: `i=1000001..2000000`. +3. ...그리고 계속, `while`은 `i`가 `1000000` 으로 균등하게 나뉘어져 있는지 확인합니다. -Then the next call is scheduled in `(**)` if we're not done yet. +그리고 끝나지 않았다면 다음 호출이 `(**)` 안에 스케줄 됩니다. -Pauses between `count` executions provide just enough "breath" for the JavaScript engine to do something else, to react to other user actions. +`count` 실행 사이의 일시 중지는 자바스크립트 엔진이 다른 작업을 수행하고 다른 사용자 작업에 반응할 수 있을 정도의 "숨실수" 있는 환경을 제공합니다. -The notable thing is that both variants -- with and without splitting the job by `setTimeout` -- are comparable in speed. There's no much difference in the overall counting time. +중요한 것은 -- `setTimeout` 으로 작업을 나누든 나누지 않든 -- 속도 면에서 비슷하다는 것입니다. 전체 계산 시간에는 별다른 차이가 없습니다. -To make them closer, let's make an improvement. +이것을 좀 더 알아보기 위해 개선해 보겠습니다. -We'll move the scheduling in the beginning of the `count()`: +`count()`의 초반에 스케줄 하는 부분을 옮기겠습니다: ```js run let i = 0; @@ -354,14 +354,14 @@ function count() { count(); ``` -Now when we start to `count()` and know that we'll need to `count()` more, we schedule that immediately, before doing the job. +이제 `count()`가 시작되고 `count()`가 더 필요하다는 걸 알게 됩니다, 작업을 하기 전에 그것을 바로 스케줄 합니다. -If you run it, it's easy to notice that it takes significantly less time. +만약에 실행하면, 훨씬 적은 시간이 걸리는 것을 쉽게 알 수 있습니다. -````smart header="Minimal delay of nested timers in-browser" -In the browser, there's a limitation of how often nested timers can run. The [HTML5 standard](https://www.w3.org/TR/html5/webappapis.html#timers) says: "after five nested timers, the interval is forced to be at least four milliseconds.". +````smart header="브라우저에서 중첩된 타이머의 지연 최소화" +브라우저에는 중첩 타이머를 실행할 수 있는 빈도의 한계가 있습니다. [HTML5 standard](https://www.w3.org/TR/html5/webappapis.html#timers)에서 언급하길: "다섯 개의 중첩 된 타이머 이후에 간격은 적어도 4밀리 초가 되어야 합니다.". -Let's demonstrate what it means with the example below. The `setTimeout` call in it re-schedules itself after `0ms`. Each call remembers the real time from the previous one in the `times` array. What do the real delays look like? Let's see: +아래 예를 통해 의미를 설명해 보겠습니다. `setTimeout` 호출은 `0ms` 후에 자신을 스케줄 합니다. 각 호출은 `times` 배열에 있는 이전 호출로부터 실시간을 기억합니다. 실제 지연은 어떠한가요? 살펴보겠습니다. ```js run let start = Date.now(); @@ -378,20 +378,20 @@ setTimeout(function run() { // 1,1,1,1,9,15,20,24,30,35,40,45,50,55,59,64,70,75,80,85,90,95,100 ``` -First timers run immediately (just as written in the spec), and then the delay comes into play and we see `9, 15, 20, 24...`. +첫 번째 타이머는 즉시 실행되고 (규격과 마찬가지로) 지연이 발생하고 '9, 15, 20, 24 ...'라고 표시됩니다. 이러한 제한은 오래전부터 전해왔으며 많은 스크립트가 사용하므로, 아직도 역사적인 이유로 남아있습니다. -That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons. +서버 측 자바스크립트의 경우, 이러한 제한은 존재하지 않으며 즉시 비동기 작업을 스케줄 하는 다른 방법이 있습니다. -For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html) for Node.js. So the notion is browser-specific only. +Node.JS 에는 [process.nextTick](https://nodejs.org/api/process.html) 와 [setImmediate](https://nodejs.org/api/timers.html) 가 있습니다. 그래서 위의 개념은 브라우저마다 다릅니다. ```` -### Allowing the browser to render +### 브라우저에서 렌더링 허용 -Another benefit for in-browser scripts is that they can show a progress bar or something to the user. That's because the browser usually does all "repainting" after the script is complete. +브라우저 내 스크립트의 또 다른 이점은 진행률 표시처럼 사용자에게 무언가를 보여줄 수 있다는 것입니다. 스크립트가 완료된 후 브라우저가 일반적으로 "다시 그리기"를 실행하기 때문입니다. -So if we do a single huge function then even if it changes something, the changes are not reflected in the document till it finishes. +따라서 하나의 커다란 기능을 수행하는 경우 무언가를 변경하더라도 변경 사항은 문서가 완료될 때까지 반영되지 않습니다. -Here's the demo: +여기 예제가 있습니다: ```html run
@@ -411,9 +411,9 @@ Here's the demo: ``` -If you run it, the changes to `i` will show up after the whole count finishes. +실행하면 전체 카운트가 끝난 후 'i'의 변경 사항이 표시됩니다. -And if we use `setTimeout` to split it into pieces then changes are applied in-between the runs, so this looks better: +그리고 만약 `setTimeout`을 조각으로 나눠서 사용한다면, 변경이 실행 사이에 적용됩니다. ```html run
@@ -439,24 +439,24 @@ And if we use `setTimeout` to split it into pieces then changes are applied in-b ``` -Now the `
` shows increasing values of `i`. +이제 `
` 는 `i` 의 값이 증가하는 것을 보여줍니다. -## Summary +## 요약 -- Methods `setInterval(func, delay, ...args)` and `setTimeout(func, delay, ...args)` allow to run the `func` regularly/once after `delay` milliseconds. -- To cancel the execution, we should call `clearInterval/clearTimeout` with the value returned by `setInterval/setTimeout`. -- Nested `setTimeout` calls is a more flexible alternative to `setInterval`. Also they can guarantee the minimal time *between* the executions. -- Zero-timeout scheduling `setTimeout(...,0)` is used to schedule the call "as soon as possible, but after the current code is complete". +- `setInterval(func, delay, ...args)` 와 `setTimeout(func, delay, ...args)` 메서드는 `delay` 밀리 세컨드만큼 후에 `func` 을 규칙적으로/ 또는 한번 실행되도록 허용한다. +- 실행을 취소하기 위해서는 `setInterval/setTimeout` 에서 반환된 값으로 `clearInterval/clearTimeout` 를 호출한다. +- 중첩된 `setTimeout` 은 `setInterval` 보다 더 나은 대안이 될 수 있습니다. 또한 실행단계들 *사이에서* 최소한의 시간을 보장한다. +- 시간 설정이 되지 않은 `setTimeout(...,0)` 은 "현재 코드가 완료된 후 가능한 한 빠르게" 호출하게 할 때 사용된다. -Some use cases of `setTimeout(...,0)`: -- To split CPU-hungry tasks into pieces, so that the script doesn't "hang" -- To let the browser do something else while the process is going on (paint the progress bar). +`setTimeout(...,0)`가 사용되는 경우: +- CPU를 많이 먹는 작업을 작게 나누어 스크립트가 "정지"하는 경우가 없게 할 때. +- 브라우저가 프로세스를 하는 동안(프로그레스 바를 칠하는 것 같은) 무언가 다른 것을 할 수 있게 하고 싶을 때. -Please note that all scheduling methods do not *guarantee* the exact delay. We should not rely on that in the scheduled code. +모든 스케줄 하는 방법들은 정확한 딜레이를 *보장*하지 않습니다. 스케줄 된 코드에 그것을 의존해서는 안 됩니다. -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. +예를 들면, 브라우저에 탑재된 타이머는 여러 가지 이유로 느려질 수 있습니다. +- CPU가 오버로드 되었다. +- 브라우저 탭이 백그라운드 모드가 되었다. +- 노트북이 배터리 모드 일 때. -All that may increase the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and settings. +최소한 브라우저 해상도와 설정에 따라 최소 타이머 해상도 (최소 지연 시간)를 300ms 또는 1000ms까지 늘릴 수 있습니다.