Skip to content

Commit a6cdc5e

Browse files
committed
Merge pull request BonsaiDen#108 from dogfeet/ko
Korean Translation
2 parents 4a93411 + 39f0b9f commit a6cdc5e

24 files changed

+1583
-1
lines changed

doc/ko/array/constructor.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## `Array` 생성자
2+
3+
`Array` 생성자가 파라미터를 처리하는 방법은 모호하기 때문에 항상 `[]` 노테이션으로 Array를 만들어야 한다.
4+
5+
[1, 2, 3]; // Result: [1, 2, 3]
6+
new Array(1, 2, 3); // Result: [1, 2, 3]
7+
8+
[3]; // Result: [3]
9+
new Array(3); // Result: []
10+
new Array('3') // Result: ['3']
11+
12+
`Array` 생성자에 인자로 숫자 하나를 넘기면 생성자는 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환한다. 생성자는 **오직** `length` 프로퍼티에 할당하기만 하고 실제 `Array`는 초기화하지 않는다는 것을 기억해야 한다.
13+
14+
var arr = new Array(3);
15+
arr[1]; // undefined
16+
1 in arr; // false, 이 인덱스는 초기화되지 않음.
17+
18+
Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더하는 경우가 그렇다.
19+
20+
new Array(count + 1).join(stringToRepeat);
21+
22+
### 결론
23+
24+
`Array` 생성자는 가능하면 사용하지 말아야 한다. `[]` 노테이션이 더 알맞다. 더 간략하고 명확하기 때문에 보기도 좋다.

doc/ko/array/general.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## Array Iteration과 프로퍼티
2+
3+
JavaScript에서는 Array도 객체지만 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다.
4+
5+
> **Note:** JavaScript의 Array는 *Associative Array***아니다**. JavaScript [객체](#object.general)는 key/value만 mapping 할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다.
6+
7+
`for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다.
8+
9+
### Iteration
10+
11+
Array를 Iterate 할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다.
12+
13+
var list = [1, 2, 3, 4, 5, ...... 100000000];
14+
for(var i = 0, l = list.length; i < l; i++) {
15+
console.log(list[i]);
16+
}
17+
18+
위 예제에서 꼭 기억해야 하는 것은 `l = list.length`로 Array의 length 값을 캐시 했다는 것이다.
19+
20+
Array에 있는 `length` 프로퍼티를 iterate마다 사용하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리하기도 하지만 코드가 새 엔진에서 실행되도록 보장할 방법이 없다.
21+
22+
실제로 캐시 하지 않으면 성능이 반으로 줄어든다.
23+
24+
### `length` 프로퍼티
25+
26+
`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 할당한 수로 Array를 잘라 버린다.
27+
28+
var foo = [1, 2, 3, 4, 5, 6];
29+
foo.length = 3;
30+
foo; // [1, 2, 3]
31+
32+
foo.length = 6;
33+
foo; // [1, 2, 3]
34+
35+
현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당하면 아무것도 하지 않는다.
36+
37+
### 결론
38+
39+
최적의 성능을 위해서 `for`를 사용하고 `length` 프로퍼티 값을 캐시 하길 바란다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다.

doc/ko/core/delete.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
## `delete`
2+
3+
간단히 말해서 global 변수, 함수, 등은 `DontDelete` 속성이기 때문에 삭제 못 한다.
4+
5+
### Global 코드와 함수 코드
6+
7+
Global이나 Function scope에 정의된 함수나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete`속성을 가진다. Global이나 Function 코드에서 변수나 함수의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 삭제할 수 없다:
8+
9+
// Global 변수:
10+
var a = 1; // DontDelete가 설정된다.
11+
delete a; // false
12+
a; // 1
13+
14+
// 함수:
15+
function f() {} // DontDelete가 설정된다.
16+
delete f; // false
17+
typeof f; // "function"
18+
19+
// 다시 할당해도 삭제할 수 없다:
20+
f = 1;
21+
delete f; // false
22+
f; // 1
23+
24+
### Explicit 프로퍼티
25+
26+
다음 예제에서 만드는 property는 정상적으로 지워진다. 이런 걸 Explicit 프로퍼티라고 부른다:
27+
28+
// Explicit 프로퍼티를 만든다:
29+
var obj = {x: 1};
30+
obj.y = 2;
31+
delete obj.x; // true
32+
delete obj.y; // true
33+
obj.x; // undefined
34+
obj.y; // undefined
35+
36+
`obj.x``obj.y``DontDelete` 속성이 아녀서 삭제된다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다.:
37+
38+
// IE를 빼고 잘 동작한다.:
39+
var GLOBAL_OBJECT = this;
40+
GLOBAL_OBJECT.a = 1;
41+
a === GLOBAL_OBJECT.a; // true - 진짜 Global 변순지 확인하는 것
42+
delete GLOBAL_OBJECT.a; // true
43+
GLOBAL_OBJECT.a; // undefined
44+
45+
[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다.
46+
47+
IE (적어도 6-8)는 버그가 있어서 안 된다.
48+
49+
### arguments와 함수의 기본 프로퍼티
50+
51+
함수의 [`arguments` 객체](#function.arguments)와 built-in 프로퍼티도 `DontDelete` 속성이다.
52+
53+
// 함수의 arguments와 프로퍼티:
54+
(function (x) {
55+
56+
delete arguments; // false
57+
typeof arguments; // "object"
58+
59+
delete x; // false
60+
x; // 1
61+
62+
function f(){}
63+
delete f.length; // false
64+
typeof f.length; // "number"
65+
66+
})(1);
67+
68+
### Host 객체
69+
70+
(역주, Host 객체들은 document같은 DOM 객체를 말한다.)
71+
72+
Host 객체를 delete하면 어떻게 될지 알 수 없다. 어떻게 Host 객체를 delete해야 하는지 표준에 정의되지 않았다.
73+
74+
### 결론
75+
76+
`delete` 연산자는 엉뚱하게 동작할 때가 잦다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다.

doc/ko/core/eval.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
## `eval`을 사용하면 안 될까?
2+
3+
`eval` 함수는 스트링으로 된 JavaScript 코드를 Local Scope에서 실행한다.
4+
5+
var foo = 1;
6+
function test() {
7+
var foo = 2;
8+
eval('foo = 3');
9+
return foo;
10+
}
11+
test(); // 3
12+
foo; // 1
13+
14+
`eval``eval`이라는 이름으로 **직접** 직행할 때에만 Local Scope에서 실행된다.
15+
16+
var foo = 1;
17+
function test() {
18+
var foo = 2;
19+
var bar = eval;
20+
bar('foo = 3');
21+
return foo;
22+
}
23+
test(); // 2
24+
foo; // 3
25+
26+
어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 경우의 99.9%는 사실 eval이 필요 없다.
27+
28+
### 가짜 `eval`
29+
30+
[timeout functions](#other.timeouts)`setTimeout``setInterval`은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아녀서 항상 global scope에서 실행된다.
31+
32+
### 보안 이슈
33+
34+
`eval`은 보안 문제도 있다. 단순히 **모든** 코드를 실행하기 때문에 신뢰하지 못하는 코드가 **절대로** 포함되지 않도록 주의해야 한다.
35+
36+
### 결론
37+
38+
`eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그의 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다.

doc/ko/core/semicolon.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
## 세미콜론을 자동으로 삽입해준다.
2+
3+
JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 semicolon을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다.
4+
5+
사실 JavaScript는 semicolon이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 semicolon이 없으면 **자동으로** semicolon을 추가한다.
6+
7+
var foo = function() {
8+
} // 세미콜론이 없으니 에러 난다.
9+
test()
10+
11+
파서는 세미콜론을 삽입하고 다시 시도한다.
12+
13+
var foo = function() {
14+
}; // 에러가 없어짐.
15+
test()
16+
17+
JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** 설계 오류 중 하나다. 세미콜론 유무에 따라 *전혀* 다른 코드가 될 수 있다.
18+
19+
### 어떻게 다를까?
20+
21+
코드에 세미콜론이 없으면 파서가 어디에 넣을지 결정한다.
22+
23+
(function(window, undefined) {
24+
function test(options) {
25+
log('testing!')
26+
27+
(options.list || []).forEach(function(i) {
28+
29+
})
30+
31+
options.value.test(
32+
'long string to pass here',
33+
'and another long string to pass'
34+
)
35+
36+
return
37+
{
38+
foo: function() {}
39+
}
40+
}
41+
window.test = test
42+
43+
})(window)
44+
45+
(function(window) {
46+
window.someLibrary = {}
47+
48+
})(window)
49+
50+
파서는 다음과 같이 삽입한다.
51+
52+
(function(window, undefined) {
53+
function test(options) {
54+
55+
// 세미콜론을 넣는 것이 아니라 줄을 합친다.
56+
log('testing!')(options.list || []).forEach(function(i) {
57+
58+
}); // <- 여기
59+
60+
options.value.test(
61+
'long string to pass here',
62+
'and another long string to pass'
63+
); // <- 여기
64+
65+
return; // <- 여기에 넣어서 그냥 반환시킨다.
66+
{ // 파서는 단순 블럭이라고 생각하고
67+
68+
// 단순한 레이블과 함수
69+
foo: function() {}
70+
}; // <- 여기
71+
}
72+
window.test = test; // <- 여기
73+
74+
// 이 줄도 합쳐진다.
75+
})(window)(function(window) {
76+
window.someLibrary = {}; // <- 여기
77+
78+
})(window); //<- 여기에 파서는 세미콜론을 넣는다.
79+
80+
> **주의:** JavaScript 파서는 new line 문자가 뒤따라 오는 return 구문을 제대로 처리하지 못한다. 자동으로 세미콜론을 넣는 것 자체의 문제는 아니지만 어쨌든 여전히 문제로 남아있다.
81+
82+
파서는 완전히 다른 코드로 만들어 버린다. 이것은 **오류**다.
83+
84+
### Parenthesis
85+
86+
세미콜론 없이 괄호가 붙어 있으면 파서는 세미콜론을 넣지 않는다.
87+
88+
log('testing!')
89+
(options.list || []).forEach(function(i) {})
90+
91+
파서는 다음과 같이 코드를 바꾼다.
92+
93+
log('testing!')(options.list || []).forEach(function(i) {})
94+
95+
`log` 함수가 함수를 반환할 가능성은 거의 없다. 아마도 `undefined is not a function`이라는 `TypeError`가 발생할 거다.
96+
97+
### 결론
98+
99+
세미콜론은 반드시 사용해야 한다. 그리고 `{}`도 생략하지 않고 꼭 사용하는 것이 좋다. 한 줄밖에 안 되는 `if` / `else` 블럭에서도 꼭 사용해야 한다. 이 두 가지 규칙을 잘 지키면 JavaScript 파서가 잘못 해석하는 일을 미리 방지하고 코드도 튼튼해진다.

doc/ko/core/undefined.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## `undefined``null`
2+
3+
JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다.
4+
5+
### `undefined`도 변수
6+
7+
`undefined``undefined`라는 값을 가지는 데이터 형식이다.
8+
9+
`undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 Global 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 Global 변수의 값을 쉽게 바꿀 수 있다.
10+
11+
> **ES5 Note:** ECMAScript 5의 strict 모드에서는 `undefined`를 더는 바꿀 수 없도록 했다. 하지만 `undefined`라는 함수를 만들면 여전히 할당할 수 있다.
12+
13+
`undefined` 값이 반환될 때:
14+
15+
- global 변수 `undefined`에 접근할 때.
16+
- `return` 구문이 없는 함수는 `undefined`를 반환함.
17+
- `return` 구문으로 아무것도 반환하지 않을 때.
18+
- 없는 프로퍼티를 찾을 때.
19+
- 함수 인자가 생략될 때.
20+
- `undefined`가 할당된 모든 것.
21+
22+
### `undefined`가 바뀔 때를 대비하기
23+
24+
global 변수 `undefined``undefined`라는 객체를 가리키는 것뿐이기 때문에 새로운 값을 할당한다고 해도 `undefined`의 값 자체가 바뀌는 것이 아니다.
25+
26+
그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다.
27+
28+
보통 `undefined` 변수가 바뀌어 있을 때를 대비해서 undefined라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다.
29+
30+
var undefined = 123;
31+
(function(something, foo, undefined) {
32+
// Local Scope에 undefined를 만들어서
33+
// 원래 값을 가리키도록 했다.
34+
35+
})('Hello World', 42);
36+
37+
wrapper 안에서 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다.
38+
39+
var undefined = 123;
40+
(function(something, foo) {
41+
var undefined;
42+
...
43+
44+
})('Hello World', 42);
45+
46+
이 두 방법의 차이는 minified했을 때 4바이트만큼 차이 난다는 것과 한쪽은 wrapper 안에 var 구문이 없다는 것밖에 없다.
47+
48+
### `Null` 객체의 용도
49+
50+
JavaScript 언어에서는 `undefined`를 다른 언어에서 *null*을 사용하듯이 쓰고 진짜 `null`은 그냥 다른 데이터 타입 중 하나일 뿐이다.
51+
52+
JavaScript 내부적인 곳에 사용하는 경우가 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다).

0 commit comments

Comments
 (0)