Skip to content

Commit

Permalink
Merge pull request #108 from dogfeet/ko
Browse files Browse the repository at this point in the history
Korean Translation
  • Loading branch information
ZhangYiJiang committed Nov 18, 2011
2 parents 4a93411 + 39f0b9f commit a6cdc5e
Show file tree
Hide file tree
Showing 24 changed files with 1,583 additions and 1 deletion.
24 changes: 24 additions & 0 deletions doc/ko/array/constructor.md
@@ -0,0 +1,24 @@
## `Array` 생성자

`Array` 생성자가 파라미터를 처리하는 방법은 모호하기 때문에 항상 `[]` 노테이션으로 Array를 만들어야 한다.

[1, 2, 3]; // Result: [1, 2, 3]
new Array(1, 2, 3); // Result: [1, 2, 3]

[3]; // Result: [3]
new Array(3); // Result: []
new Array('3') // Result: ['3']

`Array` 생성자에 인자로 숫자 하나를 넘기면 생성자는 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환한다. 생성자는 **오직** `length` 프로퍼티에 할당하기만 하고 실제 `Array`는 초기화하지 않는다는 것을 기억해야 한다.

var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, 이 인덱스는 초기화되지 않음.

Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더하는 경우가 그렇다.

new Array(count + 1).join(stringToRepeat);

### 결론

`Array` 생성자는 가능하면 사용하지 말아야 한다. `[]` 노테이션이 더 알맞다. 더 간략하고 명확하기 때문에 보기도 좋다.
39 changes: 39 additions & 0 deletions doc/ko/array/general.md
@@ -0,0 +1,39 @@
## Array Iteration과 프로퍼티

JavaScript에서는 Array도 객체지만 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다.

> **Note:** JavaScript의 Array는 *Associative Array***아니다**. JavaScript [객체](#object.general)는 key/value만 mapping 할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다.
`for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다.

### Iteration

Array를 Iterate 할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다.

var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}

위 예제에서 꼭 기억해야 하는 것은 `l = list.length`로 Array의 length 값을 캐시 했다는 것이다.

Array에 있는 `length` 프로퍼티를 iterate마다 사용하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리하기도 하지만 코드가 새 엔진에서 실행되도록 보장할 방법이 없다.

실제로 캐시 하지 않으면 성능이 반으로 줄어든다.

### `length` 프로퍼티

`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 할당한 수로 Array를 잘라 버린다.

var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]

foo.length = 6;
foo; // [1, 2, 3]

현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당하면 아무것도 하지 않는다.

### 결론

최적의 성능을 위해서 `for`를 사용하고 `length` 프로퍼티 값을 캐시 하길 바란다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다.
76 changes: 76 additions & 0 deletions doc/ko/core/delete.md
@@ -0,0 +1,76 @@
## `delete`

간단히 말해서 global 변수, 함수, 등은 `DontDelete` 속성이기 때문에 삭제 못 한다.

### Global 코드와 함수 코드

Global이나 Function scope에 정의된 함수나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete`속성을 가진다. Global이나 Function 코드에서 변수나 함수의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 삭제할 수 없다:

// Global 변수:
var a = 1; // DontDelete가 설정된다.
delete a; // false
a; // 1

// 함수:
function f() {} // DontDelete가 설정된다.
delete f; // false
typeof f; // "function"

// 다시 할당해도 삭제할 수 없다:
f = 1;
delete f; // false
f; // 1

### Explicit 프로퍼티

다음 예제에서 만드는 property는 정상적으로 지워진다. 이런 걸 Explicit 프로퍼티라고 부른다:

// Explicit 프로퍼티를 만든다:
var obj = {x: 1};
obj.y = 2;
delete obj.x; // true
delete obj.y; // true
obj.x; // undefined
obj.y; // undefined

`obj.x``obj.y``DontDelete` 속성이 아녀서 삭제된다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다.:

// IE를 빼고 잘 동작한다.:
var GLOBAL_OBJECT = this;
GLOBAL_OBJECT.a = 1;
a === GLOBAL_OBJECT.a; // true - 진짜 Global 변순지 확인하는 것
delete GLOBAL_OBJECT.a; // true
GLOBAL_OBJECT.a; // undefined

[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다.

IE (적어도 6-8)는 버그가 있어서 안 된다.

### arguments와 함수의 기본 프로퍼티

함수의 [`arguments` 객체](#function.arguments)와 built-in 프로퍼티도 `DontDelete` 속성이다.

// 함수의 arguments와 프로퍼티:
(function (x) {

delete arguments; // false
typeof arguments; // "object"
delete x; // false
x; // 1
function f(){}
delete f.length; // false
typeof f.length; // "number"
})(1);

### Host 객체

(역주, Host 객체들은 document같은 DOM 객체를 말한다.)

Host 객체를 delete하면 어떻게 될지 알 수 없다. 어떻게 Host 객체를 delete해야 하는지 표준에 정의되지 않았다.

### 결론

`delete` 연산자는 엉뚱하게 동작할 때가 잦다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다.
38 changes: 38 additions & 0 deletions doc/ko/core/eval.md
@@ -0,0 +1,38 @@
## `eval`을 사용하면 안 될까?

`eval` 함수는 스트링으로 된 JavaScript 코드를 Local Scope에서 실행한다.

var foo = 1;
function test() {
var foo = 2;
eval('foo = 3');
return foo;
}
test(); // 3
foo; // 1

`eval``eval`이라는 이름으로 **직접** 직행할 때에만 Local Scope에서 실행된다.

var foo = 1;
function test() {
var foo = 2;
var bar = eval;
bar('foo = 3');
return foo;
}
test(); // 2
foo; // 3

어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 경우의 99.9%는 사실 eval이 필요 없다.

### 가짜 `eval`

[timeout functions](#other.timeouts)`setTimeout``setInterval`은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아녀서 항상 global scope에서 실행된다.

### 보안 이슈

`eval`은 보안 문제도 있다. 단순히 **모든** 코드를 실행하기 때문에 신뢰하지 못하는 코드가 **절대로** 포함되지 않도록 주의해야 한다.

### 결론

`eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그의 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다.
99 changes: 99 additions & 0 deletions doc/ko/core/semicolon.md
@@ -0,0 +1,99 @@
## 세미콜론을 자동으로 삽입해준다.

JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 semicolon을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다.

사실 JavaScript는 semicolon이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 semicolon이 없으면 **자동으로** semicolon을 추가한다.

var foo = function() {
} // 세미콜론이 없으니 에러 난다.
test()

파서는 세미콜론을 삽입하고 다시 시도한다.

var foo = function() {
}; // 에러가 없어짐.
test()

JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** 설계 오류 중 하나다. 세미콜론 유무에 따라 *전혀* 다른 코드가 될 수 있다.

### 어떻게 다를까?

코드에 세미콜론이 없으면 파서가 어디에 넣을지 결정한다.

(function(window, undefined) {
function test(options) {
log('testing!')

(options.list || []).forEach(function(i) {

})

options.value.test(
'long string to pass here',
'and another long string to pass'
)

return
{
foo: function() {}
}
}
window.test = test

})(window)

(function(window) {
window.someLibrary = {}

})(window)

파서는 다음과 같이 삽입한다.

(function(window, undefined) {
function test(options) {

// 세미콜론을 넣는 것이 아니라 줄을 합친다.
log('testing!')(options.list || []).forEach(function(i) {

}); // <- 여기

options.value.test(
'long string to pass here',
'and another long string to pass'
); // <- 여기

return; // <- 여기에 넣어서 그냥 반환시킨다.
{ // 파서는 단순 블럭이라고 생각하고

// 단순한 레이블과 함수
foo: function() {}
}; // <- 여기
}
window.test = test; // <- 여기

// 이 줄도 합쳐진다.
})(window)(function(window) {
window.someLibrary = {}; // <- 여기

})(window); //<- 여기에 파서는 세미콜론을 넣는다.

> **주의:** JavaScript 파서는 new line 문자가 뒤따라 오는 return 구문을 제대로 처리하지 못한다. 자동으로 세미콜론을 넣는 것 자체의 문제는 아니지만 어쨌든 여전히 문제로 남아있다.
파서는 완전히 다른 코드로 만들어 버린다. 이것은 **오류**다.

### Parenthesis

세미콜론 없이 괄호가 붙어 있으면 파서는 세미콜론을 넣지 않는다.

log('testing!')
(options.list || []).forEach(function(i) {})

파서는 다음과 같이 코드를 바꾼다.

log('testing!')(options.list || []).forEach(function(i) {})

`log` 함수가 함수를 반환할 가능성은 거의 없다. 아마도 `undefined is not a function`이라는 `TypeError`가 발생할 거다.

### 결론

세미콜론은 반드시 사용해야 한다. 그리고 `{}`도 생략하지 않고 꼭 사용하는 것이 좋다. 한 줄밖에 안 되는 `if` / `else` 블럭에서도 꼭 사용해야 한다. 이 두 가지 규칙을 잘 지키면 JavaScript 파서가 잘못 해석하는 일을 미리 방지하고 코드도 튼튼해진다.
52 changes: 52 additions & 0 deletions doc/ko/core/undefined.md
@@ -0,0 +1,52 @@
## `undefined``null`

JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다.

### `undefined`도 변수

`undefined``undefined`라는 값을 가지는 데이터 형식이다.

`undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 Global 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 Global 변수의 값을 쉽게 바꿀 수 있다.

> **ES5 Note:** ECMAScript 5의 strict 모드에서는 `undefined`를 더는 바꿀 수 없도록 했다. 하지만 `undefined`라는 함수를 만들면 여전히 할당할 수 있다.
`undefined` 값이 반환될 때:

- global 변수 `undefined`에 접근할 때.
- `return` 구문이 없는 함수는 `undefined`를 반환함.
- `return` 구문으로 아무것도 반환하지 않을 때.
- 없는 프로퍼티를 찾을 때.
- 함수 인자가 생략될 때.
- `undefined`가 할당된 모든 것.

### `undefined`가 바뀔 때를 대비하기

global 변수 `undefined``undefined`라는 객체를 가리키는 것뿐이기 때문에 새로운 값을 할당한다고 해도 `undefined`의 값 자체가 바뀌는 것이 아니다.

그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다.

보통 `undefined` 변수가 바뀌어 있을 때를 대비해서 undefined라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다.

var undefined = 123;
(function(something, foo, undefined) {
// Local Scope에 undefined를 만들어서
// 원래 값을 가리키도록 했다.

})('Hello World', 42);

wrapper 안에서 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다.

var undefined = 123;
(function(something, foo) {
var undefined;
...

})('Hello World', 42);

이 두 방법의 차이는 minified했을 때 4바이트만큼 차이 난다는 것과 한쪽은 wrapper 안에 var 구문이 없다는 것밖에 없다.

### `Null` 객체의 용도

JavaScript 언어에서는 `undefined`를 다른 언어에서 *null*을 사용하듯이 쓰고 진짜 `null`은 그냥 다른 데이터 타입 중 하나일 뿐이다.

JavaScript 내부적인 곳에 사용하는 경우가 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다).

0 comments on commit a6cdc5e

Please sign in to comment.