10
10
console.log(i); // 10
11
11
}
12
12
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 ) ,可能會造成一些不易察覺的錯誤。
17
15
16
+ JavaScript 中沒有寫示的命名空間定義,這代表著它所有定義的東西都是 * 全域共享* 在同一個命名空間下。
18
17
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 ` 錯誤碼。
25
20
26
21
### 全域變數的壞處
27
22
@@ -31,17 +26,14 @@ still has not found the requested name, it will raise a `ReferenceError`.
31
26
// script B
32
27
var foo = '42'
33
28
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 ` 在目前的區間內。
37
30
38
- Again, that is ** not** at all the * same effect* : not using ` var ` can have major
39
- implications.
31
+ 再次強調,上面的效果是 ** 完全不同** ,不使用 ` var ` 會導致隱性的全域變數。
40
32
41
- // global scope
33
+ // 全域作用區
42
34
var foo = 42;
43
35
function test() {
44
- // local scope
36
+ // 局部作用區
45
37
foo = 21;
46
38
}
47
39
test();
@@ -51,52 +43,51 @@ Leaving out the `var` statement inside the function `test` will override the
51
43
value of ` foo ` . While this might not seem like a big deal at first, having
52
44
thousands of lines of JavaScript and not using ` var ` will introduce horrible,
53
45
hard-to-track-down bugs.
46
+ 在函數 ` test ` 中部使用 ` var ` 會覆蓋到原本在外面的 ` foo ` 。
47
+ 雖然看起來不是什麼大問題,但是當程式有幾千行的時候沒有使用 ` var ` 會照成難以追蹤的臭蟲。
48
+
54
49
55
- // global scope
50
+ // 全域作用域
56
51
var items = [/* some list */];
57
52
for(var i = 0; i < 10; i++) {
58
53
subLoop();
59
54
}
60
55
61
56
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
+ // 做一些事情
65
60
}
66
61
}
67
62
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 ` ,除非就是 ` 希望他的效果 ` 是取改變外部的作用域。
72
66
73
- ### Local Variables
67
+ ### 局部變數
74
68
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 ` 來宣告變數。
78
71
79
- // global scope
72
+ // 全域變數
80
73
var foo = 1;
81
74
var bar = 2;
82
75
var i = 2;
83
76
84
77
function test(i) {
85
- // local scope of the function test
78
+ // 函式 test 內部的局部作用域
86
79
i = 5;
87
80
88
81
var foo = 3;
89
82
bar = 4;
90
83
}
91
84
test(10);
92
85
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 ` 的賦值會覆蓋全區域的作用域內的同名變數。
95
87
96
- ### Hoisting
88
+ ### 變數宣告
97
89
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 ` 的圈告都會被提升到當前作用域的頂端。
100
91
101
92
bar();
102
93
var bar = function() {};
@@ -115,16 +106,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and
115
106
}
116
107
}
117
108
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 ` 宣告,放到最頂端最接近的作用區間
121
110
122
- // var statements got moved here
123
- var bar, someValue; // default to 'undefined'
111
+ // var 被移到這裡
112
+ var bar, someValue; // 值等於 'undefined'
124
113
125
- // the function declaration got moved up too
114
+ // function 的宣告也被搬上來
126
115
function test(data) {
127
- var goo, i, e; // missing block scope moves these here
116
+ var goo, i, e; // 沒有作用域的也被搬至頂端
128
117
if (false) {
129
118
goo = 1;
130
119
@@ -136,98 +125,79 @@ nearest surrounding scope.
136
125
}
137
126
}
138
127
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; // 賦值語句不會被提昇規則影響
141
130
bar = function() {};
142
131
143
132
test();
144
133
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 ` 表達式更難看懂。
148
135
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 ` ,但實際上在提昇規則被運用後,卻是在修改 * 局部變數*
152
137
153
- Without knowledge of * hoisting* , one might suspect the code below would raise a
154
- ` ReferenceError ` .
138
+ 如果沒有提昇規則的話,可能會出現像下面的看起來會出現 ` ReferenceError ` 的錯誤。
155
139
156
- // check whether SomeImportantThing has been initialized
140
+ // 檢查 SomeImportantThing 是否已經被初始化
157
141
if (!SomeImportantThing) {
158
142
var SomeImportantThing = {};
159
143
}
160
144
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 ` 的表達式會被提升到 * 全域作用域* 的頂端。
163
146
164
147
var SomeImportantThing;
165
148
166
- // other code might initialize SomeImportantThing here, or not
149
+ // 有些程式,可能會初始化。
150
+ SomeImportantThing here, or not
167
151
168
- // make sure it's there
152
+ // 檢查是否已經被初始化。
169
153
if (!SomeImportantThing) {
170
154
SomeImportantThing = {};
171
155
}
172
156
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 ) , 在它們裡面被定義,指向當前的物件
177
160
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 ) , 定義它們,其中包括傳到函式內的參數。
180
162
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 會依照下面的順序去查詢:
183
164
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 . 回溯到上一個層級然後再從第一個開始往下去查。
188
169
189
- > ** Note:** Having a parameter called ` arguments ` will ** prevent** the creation
190
- > of the default ` arguments ` object.
170
+ > ** 注意: ** 自定義 ` arguments ` 參數會阻止原生的 ` arguments ` 的物件創立
191
171
192
- ### Namespaces
172
+ ### 命名空間
193
173
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 中可以透過 * 匿名包裝器* 來解決。
197
175
198
176
(function() {
199
- // a self contained "namespace"
177
+ // 自己本身的匿名空間
200
178
201
179
window.foo = function() {
202
- // an exposed closure
180
+ // 對外公開的函式
203
181
};
204
182
205
- })(); // execute the function immediately
183
+ })(); // 馬上執行這個匿名函式
206
184
185
+ 匿名函式被認為是 [ 表達式] ( #function.general ) 因此為了要可以調用,它們會先被執行。
207
186
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
+ ( // 小括號內的先被執行
212
188
function() {}
213
- ) // and return the function object
214
- () // call the result of the evaluation
189
+ ) // 回傳函數對象
190
+ () // 調用上面的執行結果
215
191
216
- There are other ways to evaluate and directly call the function expression
217
- which, while different in syntax, behave the same way.
192
+ 還有其他方式也可以像上面一樣調用函式的方式達到
218
193
219
- // A few other styles for directly invoking the
220
194
!function(){}()
221
195
+function(){}()
222
196
(function(){}());
223
197
// and so on...
224
198
225
199
### 結語
226
200
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
+ 建議最好是都用 * 匿名包裝器* 來封裝你的程式碼在自己的命名區間內。這不僅是要防止命名衝突也可以使得程序更有模組化。
233
202
203
+ 另外,全域變數是個 ** 不好的** 習慣,因為它會帶來錯誤和更難去維護。
0 commit comments