Skip to content

Commit 3cb2af3

Browse files
author
howardchi
committed
finished function/ scope.md
1 parent 5804c90 commit 3cb2af3

File tree

2 files changed

+161
-248
lines changed

2 files changed

+161
-248
lines changed

doc/zh-TW/function/scopes.md

Lines changed: 64 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@
1010
console.log(i); // 10
1111
}
1212

13-
> **Note:** When not used in an assignment, return statement or as a function
14-
> argument, the `{...}` notation will get interpreted as a block statement and
15-
> **not** as an object literal. This, in conjunction with
16-
> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors.
13+
> **注意:** 如果不是在賦值語句中,而是在 return 表達式或者函數參數中, `{...}` 將會作為程式碼中的解析,而不是作為物件的字面語法解析。
14+
> 如果考慮到 [自動分號插入](#core.semicolon),可能會造成一些不易察覺的錯誤。
1715
16+
JavaScript 中沒有寫示的命名空間定義,這代表著它所有定義的東西都是 *全域共享* 在同一個命名空間下。
1817

19-
There are also no distinct namespaces in JavaScript, which means that everything
20-
gets defined in one *globally shared* namespace.
21-
22-
Each time a variable is referenced, JavaScript will traverse upwards through all
23-
the scopes until it finds it. In the case that it reaches the global scope and
24-
still has not found the requested name, it will raise a `ReferenceError`.
18+
每次引用一個變數,JavaScript 會向上找整個作用域直到找到這個變數為止。
19+
如果在全域中無法找到那個變數,它會拋出 `ReferenceError` 錯誤碼。
2520

2621
### 全域變數的壞處
2722

@@ -31,17 +26,14 @@ still has not found the requested name, it will raise a `ReferenceError`.
3126
// script B
3227
var foo = '42'
3328

34-
The above two scripts do **not** have the same effect. Script A defines a
35-
variable called `foo` in the *global* scope, and script B defines a `foo` in the
36-
*current* scope.
29+
上面兩個腳本 *不會* 有同樣的效果。腳本 A 在 *全域* 空間定義了變數 `foo`,腳本 B 定義了 `foo` 在目前的區間內。
3730

38-
Again, that is **not** at all the *same effect*: not using `var` can have major
39-
implications.
31+
再次強調,上面的效果是 **完全不同**,不使用 `var` 會導致隱性的全域變數。
4032

41-
// global scope
33+
// 全域作用區
4234
var foo = 42;
4335
function test() {
44-
// local scope
36+
// 局部作用區
4537
foo = 21;
4638
}
4739
test();
@@ -51,52 +43,51 @@ Leaving out the `var` statement inside the function `test` will override the
5143
value of `foo`. While this might not seem like a big deal at first, having
5244
thousands of lines of JavaScript and not using `var` will introduce horrible,
5345
hard-to-track-down bugs.
46+
在函數 `test` 中部使用 `var` 會覆蓋到原本在外面的 `foo`
47+
雖然看起來不是什麼大問題,但是當程式有幾千行的時候沒有使用 `var` 會照成難以追蹤的臭蟲。
48+
5449

55-
// global scope
50+
// 全域作用域
5651
var items = [/* some list */];
5752
for(var i = 0; i < 10; i++) {
5853
subLoop();
5954
}
6055

6156
function subLoop() {
62-
// scope of subLoop
63-
for(i = 0; i < 10; i++) { // missing var statement
64-
// do amazing stuff!
57+
// subLoop 的作用域
58+
for(i = 0; i < 10; i++) { // 缺少了 var
59+
// 做一些事情
6560
}
6661
}
6762

68-
The outer loop will terminate after the first call to `subLoop`, since `subLoop`
69-
overwrites the global value of `i`. Using a `var` for the second `for` loop would
70-
have easily avoided this error. The `var` statement should **never** be left out
71-
unless the *desired effect* is to affect the outer scope.
63+
在外面的迴圈在呼叫第一次 `subLoop` 之後就會停止,因為 `subLoop` 全域變數中的 `i` 被覆蓋了。
64+
在第二次使用 `for` 迴圈的時候,使用 `var` 就可以避免這種錯誤。
65+
在宣告變數的時候 **絕對不要** 忘記 `var`,除非就是 `希望他的效果` 是取改變外部的作用域。
7266

73-
### Local Variables
67+
### 局部變數
7468

75-
The only source for local variables in JavaScript are
76-
[function](#function.general) parameters and variables declared via the
77-
`var` statement.
69+
在 javascript 中能用兩種方式來宣告局部變數。
70+
[函式](#function.general) 參數和透過 `var` 來宣告變數。
7871

79-
// global scope
72+
// 全域變數
8073
var foo = 1;
8174
var bar = 2;
8275
var i = 2;
8376

8477
function test(i) {
85-
// local scope of the function test
78+
// 函式 test 內部的局部作用域
8679
i = 5;
8780

8881
var foo = 3;
8982
bar = 4;
9083
}
9184
test(10);
9285

93-
While `foo` and `i` are local variables inside the scope of the function `test`,
94-
the assignment of `bar` will override the global variable with the same name.
86+
`foo``i` 是它的局部變數在 `test` 函式中,但是在 `bar` 的賦值會覆蓋全區域的作用域內的同名變數。
9587

96-
### Hoisting
88+
### 變數宣告
9789

98-
JavaScript **hoists** declarations. This means that both `var` statements and
99-
`function` declarations will be moved to the top of their enclosing scope.
90+
JavaScript 會 **提昇** 變數宣告, 這代表著 `var``function` 的圈告都會被提升到當前作用域的頂端。
10091

10192
bar();
10293
var bar = function() {};
@@ -115,16 +106,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and
115106
}
116107
}
117108

118-
The above code gets transformed before execution starts. JavaScript moves
119-
the `var` statements, as well as `function` declarations, to the top of the
120-
nearest surrounding scope.
109+
在上面的程式碼會被轉化在執行之前。 JavaScript 會把 `var`,和 `function` 宣告,放到最頂端最接近的作用區間
121110

122-
// var statements got moved here
123-
var bar, someValue; // default to 'undefined'
111+
// var 被移到這裡
112+
var bar, someValue; // 值等於 'undefined'
124113

125-
// the function declaration got moved up too
114+
// function 的宣告也被搬上來
126115
function test(data) {
127-
var goo, i, e; // missing block scope moves these here
116+
var goo, i, e; // 沒有作用域的也被搬至頂端
128117
if (false) {
129118
goo = 1;
130119

@@ -136,98 +125,79 @@ nearest surrounding scope.
136125
}
137126
}
138127

139-
bar(); // fails with a TypeError since bar is still 'undefined'
140-
someValue = 42; // assignments are not affected by hoisting
128+
bar(); // 出錯:TypeError bar 還是 'undefined'
129+
someValue = 42; // 賦值語句不會被提昇規則影響
141130
bar = function() {};
142131

143132
test();
144133

145-
Missing block scoping will not only move `var` statements out of loops and
146-
their bodies, it will also make the results of certain `if` constructs
147-
non-intuitive.
134+
沒有作用域區間不只會把 `var` 放到迴圈之外,還會使得 `if` 表達式更難看懂。
148135

149-
In the original code, although the `if` statement seemed to modify the *global
150-
variable* `goo`, it actually modifies the *local variable* - after hoisting
151-
has been applied.
136+
在一般的程式中,雖然 `if` 表達式中看起來修改了 *全域變數* `goo`,但實際上在提昇規則被運用後,卻是在修改 *局部變數*
152137

153-
Without knowledge of *hoisting*, one might suspect the code below would raise a
154-
`ReferenceError`.
138+
如果沒有提昇規則的話,可能會出現像下面的看起來會出現 `ReferenceError` 的錯誤。
155139

156-
// check whether SomeImportantThing has been initialized
140+
// 檢查 SomeImportantThing 是否已經被初始化
157141
if (!SomeImportantThing) {
158142
var SomeImportantThing = {};
159143
}
160144

161-
But of course, this works due to the fact that the `var` statement is being
162-
moved to the top of the *global scope*.
145+
但是它沒有錯誤,因為 `var` 的表達式會被提升到 *全域作用域* 的頂端。
163146

164147
var SomeImportantThing;
165148

166-
// other code might initialize SomeImportantThing here, or not
149+
// 有些程式,可能會初始化。
150+
SomeImportantThing here, or not
167151

168-
// make sure it's there
152+
// 檢查是否已經被初始化。
169153
if (!SomeImportantThing) {
170154
SomeImportantThing = {};
171155
}
172156

173-
### Name Resolution Order
174-
175-
All scopes in JavaScript, including the *global scope*, have the special name
176-
[`this`](#function.this), defined in them, which refers to the *current object*.
157+
### 名稱解析順序
158+
159+
JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊的名字 [`this`](#function.this), 在它們裡面被定義,指向當前的物件
177160

178-
Function scopes also have the name [`arguments`](#function.arguments), defined in
179-
them, which contains the arguments that were passed to the function.
161+
函式作用域也有一個名稱叫做 [`arguments`](#function.arguments), 定義它們,其中包括傳到函式內的參數。
180162

181-
For example, when trying to access a variable named `foo` inside the scope of a
182-
function, JavaScript will look up the name in the following order:
163+
例如,它們開始試著進入到 `foo` 的作用域裡面, JavaScript 會依照下面的順序去查詢:
183164

184-
1. In case there is a `var foo` statement in the current scope, use that.
185-
2. If one of the function parameters is named `foo`, use that.
186-
3. If the function itself is called `foo`, use that.
187-
4. Go to the next outer scope, and start with **#1** again.
165+
1. 當作用域內是否有 `var foo` 的定義。
166+
2. 函式形式參數是否有使用 `foo` 名稱定義。
167+
3. 函式自身是剖叫做 `foo`
168+
4. 回溯到上一個層級然後再從第一個開始往下去查。
188169

189-
> **Note:** Having a parameter called `arguments` will **prevent** the creation
190-
> of the default `arguments` object.
170+
> **注意: ** 自定義 `arguments` 參數會阻止原生的 `arguments` 的物件創立
191171
192-
### Namespaces
172+
### 命名空間
193173

194-
A common problem associated with having only one global namespace is the
195-
likelihood of running into problems where variable names clash. In JavaScript,
196-
this problem can easily be avoided with the help of *anonymous wrappers*.
174+
只有一個全域作用域會導致常見的錯誤是命名衝突。在 JavaScript 中可以透過 *匿名包裝器* 來解決。
197175

198176
(function() {
199-
// a self contained "namespace"
177+
// 自己本身的匿名空間
200178
201179
window.foo = function() {
202-
// an exposed closure
180+
// 對外公開的函式
203181
};
204182

205-
})(); // execute the function immediately
183+
})(); // 馬上執行這個匿名函式
206184

185+
匿名函式被認為是 [表達式](#function.general)因此為了要可以調用,它們會先被執行。
207186

208-
Unnamed functions are considered [expressions](#function.general); so in order to
209-
being callable, they must first be evaluated.
210-
211-
( // evaluate the function inside the parentheses
187+
( // 小括號內的先被執行
212188
function() {}
213-
) // and return the function object
214-
() // call the result of the evaluation
189+
) // 回傳函數對象
190+
() // 調用上面的執行結果
215191

216-
There are other ways to evaluate and directly call the function expression
217-
which, while different in syntax, behave the same way.
192+
還有其他方式也可以像上面一樣調用函式的方式達到
218193

219-
// A few other styles for directly invoking the
220194
!function(){}()
221195
+function(){}()
222196
(function(){}());
223197
// and so on...
224198

225199
### 結語
226200

227-
It is recommended to always use an *anonymous wrapper* to encapsulate code in
228-
its own namespace. This does not only protect code against name clashes, but it
229-
also allows for better modularization of programs.
230-
231-
Additionally, the use of global variables is considered **bad practice**. **Any**
232-
use of them indicates badly written code that is prone to errors and hard to maintain.
201+
建議最好是都用 *匿名包裝器* 來封裝你的程式碼在自己的命名區間內。這不僅是要防止命名衝突也可以使得程序更有模組化。
233202

203+
另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。

0 commit comments

Comments
 (0)