Skip to content

Commit

Permalink
translate to Tranditioin Chinese
Browse files Browse the repository at this point in the history
  • Loading branch information
howardchi committed Mar 13, 2013
1 parent a2d2b63 commit 33a89e7
Show file tree
Hide file tree
Showing 23 changed files with 1,983 additions and 0 deletions.
28 changes: 28 additions & 0 deletions doc/zh(Trandition)/array/constructor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## `Array` 的建構函式

`Array` 的建構函式在處理參數上一直有模糊的地帶,所以建議使用 `array`的字面語法來使用 - `[]` - 來新增一個的Array

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

[3]; // 結果: [3]
new Array(3); // 結果: []
new Array('3') // 結果: ['3']

在上面的範例 `new Array(3)` 當只有一個參數傳入到 `Array` 的建構函數
且那個參數事宜個數字,建構函數會回傳空值
但是 `Array` 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3)
**注意** 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化

var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, 數值沒有被設定進去

被設定用來當做 `Array` 的長度只有少數情況使用
先設定 `Array` 的長度可以用一下的範例來避免使用 `for loop` 的麻煩

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

### 結語

`Array` 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性
46 changes: 46 additions & 0 deletions doc/zh(Trandition)/array/general.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Array 迴圈和屬性

雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他
[`for in`](#object.forinloop) 的迴圈中。事實上有很多原因要避免使用 `for in` 在 Array 之中

> **注意:** Javascript Arrays **不是** *關連性 Arrays*
> 只有 [objects](#object.general) 來管理建值的相對應關係
> Arrays 是**保持** 順序的,Objects **則沒有**
因為 `for in` 迴圈會列舉所有在原型 Array 上的屬性因為他會使用[`hasOwnProperty`](#object.hasownproperty), 這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍

### 迴圈

為了要達到最好的性能所以最好使用 `for` 迴圈來讀取一個 Array 裡面的數值。

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 中其中一個屬性,但是他還使有一定的性能消耗在每次循環的訪問。
近期 Javascript 使用 **may** 來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。

實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。

### `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.push(4);
foo; // [1, 2, 3, undefined, undefined, undefined, 4]

在上面的例子可以看到,如果給的長度比較小他就會去刪除 Array 中的數值。如果比較大的話,他就會自己增加一些 `undefined` 的數值進去

### 結語

為了達到更好的效率,建議使用 `for` 迴圈還有暫存 `length` 的屬性。
`for in` 迴圈則是會讓程式中有更多的錯誤和性能問題。

85 changes: 85 additions & 0 deletions doc/zh(Trandition)/core/delete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
## The `delete` Operator

In short, it's *impossible* to delete global variables, functions and some other
stuff in JavaScript which have a `DontDelete` attribute set.

### Global code and Function code

When a variable or a function is defined in a global or a [function
scope](#function.scopes) it is a property of either the Activation object or
the Global object. Such properties have a set of attributes, one of which is
`DontDelete`. Variable and function declarations in global and function code
always create properties with `DontDelete`, and therefore cannot be deleted.

// global variable:
var a = 1; // DontDelete is set
delete a; // false
a; // 1

// normal function:
function f() {} // DontDelete is set
delete f; // false
typeof f; // "function"

// reassigning doesn't help:
f = 1;
delete f; // false
f; // 1

### Explicit properties

Explicitly set properties can be deleted normally.

// explicitly set property:
var obj = {x: 1};
obj.y = 2;
delete obj.x; // true
delete obj.y; // true
obj.x; // undefined
obj.y; // undefined

In the example above, `obj.x` and `obj.y` can be deleted because they have no
`DontDelete` atribute. That's why the example below works too.

// this works fine, except for IE:
var GLOBAL_OBJECT = this;
GLOBAL_OBJECT.a = 1;
a === GLOBAL_OBJECT.a; // true - just a global var
delete GLOBAL_OBJECT.a; // true
GLOBAL_OBJECT.a; // undefined

Here we use a trick to delete `a`. [`this`](#function.this) here refers
to the Global object and we explicitly declare variable `a` as its property
which allows us to delete it.

IE (at least 6-8) has some bugs, so the code above doesn't work.

### Function arguments and built-ins

Functions' normal arguments, [`arguments` objects](#function.arguments)
and built-in properties also have `DontDelete` set.

// function arguments and properties:
(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 objects

The behaviour of `delete` operator can be unpredictable for hosted objects. Due
to the specification, host objects are allowed to implement any kind of behavior.

### In conclusion

The `delete` operator often has unexpected behaviour and can only be safely
used to delete explicitly set properties on normal objects.
42 changes: 42 additions & 0 deletions doc/zh(Trandition)/core/eval.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## 為什麼不要使用 `eval`

因為 `eval` 函數會在 Javascript 的區域性的區間執行那段程式碼。

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

但是, `eval` 只接受直接的呼叫而且那個函數只能叫做 `eval`,才能在一個區段中執行。

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

所有的 `eval` 都應該去比免試用。有 99.9% 的使用情況都可以 **不必** 使用到而達到同等效果。

### 偽裝的 `eval`

[定時函數](#other.timeouts) `setTimeout``setInterval` 都可以接受一個字串當做他們第一個參數。這些字串 **永遠** 都會在全域範圍內執行,因此在這種情況下 `eval` 沒有被直接的使用。

### 安全上的顧慮

`eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。
而他不應去執行一串未知的字串或是來自不幸任的來源。

### 結語

`eval` 應該永遠不要去只用它,任何的程式在被他執行後都有性能和安全上的考慮。如果有情況需要去使用他,他都不應該列為第一順位的解決方法。

應該有更好的方法能夠去使用,但是最好都不要去使用 `eval`

103 changes: 103 additions & 0 deletions doc/zh(Trandition)/core/semicolon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
## 自動插入分號

雖然 JavaScript 有 C 語言的語法,但是他不強制一定要加上分號。
所以分號可以被忽略。

Javascript 並 **不是** 一個不需要分號的語言。實際上,它需要分號來讓程式碼更容易被理解。因此 Javascript 的編譯器中遇到了缺少分號的情形,它會自動的在程式碼中插入分號。

var foo = function() {
} // 編輯錯誤,因沒分號
test()

這時候編譯器在編輯的時候,會自動的加上分號,然後重新編輯。

var foo = function() {
}; // 沒有錯誤,編輯繼續
test()

自動的加入分號是被認為 **最大** 的設計缺陷之一,因為它能改變程式碼的行為。

### 工作原理

下面的程式碼中沒有使用任何的分號,所以編譯器需要去決定在哪些地方加入分號。

(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; // <- 插入分號,改變了 return 的表達行為
{ // 作為另一個程式碼的處理

// 被當做一個獨立的函數來看
foo: function() {}
}; // <- 插入分號
}
window.test = test; // <- 插入分號

// 兩行又被合併
})(window)(function(window) {
window.someLibrary = {}; // <- 插入分號

})(window); //<- 插入分號

> **注意:** 在這個範例中 Javascript 編譯器沒有正確的處理 `return` ,因為緊接的換行符號。
> 雖然這不能算是自動分號插入的錯誤,但是它是非常不樂見的效果。
編譯器在上面的程式碼中改變了原本程式碼的行為。在一些情況下,會做出 **錯誤的行為**

### 前置括號

在這種前置括號的情況下,編譯器 **不會** 自動的插入分號。

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

上面的程式碼被編譯器轉為只有一行程式

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

以上的範例中 `log`**很大** 的可能 **不是** 回傳一個函數。然而這個情況下會出現 `TypeError` 的錯誤或是會出現 `undefined is not a function` .

### 結語

建議永遠 **不要** 忽略分號。同樣的也建議大括號應在他對應的表達式在同一行。在 `if... else...`的表達式中也是如此,不應省略大括號。
這個習慣可以不僅僅是讓你的程式更一致,也可以避免編譯器因為改變程式而出錯。

70 changes: 70 additions & 0 deletions doc/zh(Trandition)/core/undefined.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## `undefined``null`

JavaScript 中有兩個表示空值的方式, `null``undefined``undefined`式比較常用的一種。

### `undefined` 的值

`undefined` 是一個值為 `undefined` 的類型。

語言中也定義了一個全域變數,它的值為 `undefined`,這個變數的被稱作 `undefined`
這個變數 **不是** 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。

> **ES5 提示: ** `undefined` 在 ECMAScript 5 裡 **不再是** *可寫*
> 但是它的名稱還是可以被隱藏,比如說定義一個函數為 `undefined`
這裡有一些例子會回傳 `undefined` 的值:

- Accessing the (unmodified) global variable `undefined`.
- Accessing a declared *but not* yet initialized variable.
- Implicit returns of functions due to missing `return` statements.
- `return` statements that do not explicitly return anything.
- Lookups of non-existent properties.
- Function parameters that do not have any explicit value passed.
- Anything that has been set to the value of `undefined`.
- Any expression in the form of `void(expression)`

### Handling Changes to the Value of `undefined`

Since the global variable `undefined` only holds a copy of the actual *value* of
`undefined`, assigning a new value to it does **not** change the value of the
*type* `undefined`.

Still, in order to compare something against the value of `undefined`, it is
necessary to retrieve the value of `undefined` first.

To protect code against a possible overwritten `undefined` variable, a common
technique used is to add an additional parameter to an [anonymous
wrapper](#function.scopes) that gets no argument passed to it.

var undefined = 123;
(function(something, foo, undefined) {
// undefined in the local scope does
// now again refer to the value `undefined`

})('Hello World', 42);

Another way to achieve the same effect would be to use a declaration inside the
wrapper.

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

})('Hello World', 42);

The only difference here is that this version results in 4 more bytes being
used in case it is minified, and there is no other `var` statement inside the
anonymous wrapper.

### Uses of `null`

While `undefined` in the context of the JavaScript language is mostly used in
the sense of a traditional *null*, the actual `null` (both a literal and a type)
is more or less just another data type.

It is used in some JavaScript internals (like declaring the end of the
prototype chain by setting `Foo.prototype = null`), but in almost all cases, it
can be replaced by `undefined`.


Loading

0 comments on commit 33a89e7

Please sign in to comment.