1- ## Scopes and Namespaces
1+ ## 作用域与命名空间( Scopes and namespaces)
22
3- Although JavaScript deals fine with the syntax of two matching curly
4- braces for blocks, it does ** not** support block scope; hence, all that is left
5- is in the language is * function scope* .
3+ 尽管 JavaScript 支持一对花括号创建的代码段,但是并不支持块级作用域;
4+ 而仅仅支持 * 函数作用域* 。
65
7- function test() { // a scope
8- for(var i = 0; i < 10; i++) { // not a scope
6+ function test() { // 一个作用域
7+ for(var i = 0; i < 10; i++) { // 不是一个作用域
98 // count
109 }
1110 console.log(i); // 10
1211 }
1312
14- > ** Note:** When not used in an assignment, return statement or as a function
15- > argument, the ` {...} ` notation will get interpreted as a block statement and
16- > ** not** as an object literal. This, in conjunction with
17- > [ automatic insertion of semicolons] ( #core.semicolon ) , can lead to subtle errors.
13+ > ** 注意:** 如果不是在赋值语句中,而是在 return 表达式或者函数参数中,` {...} ` 将会作为代码段解析,
14+ > 而不是作为对象的字面语法解析。如果考虑到 [ 自动分号插入] ( #semicolon ) ,这可能会导致一些不易察觉的错误。
1815
19- There are also no distinct namespaces in JavaScript, that means that everything
20- gets defined in one * globally shared* namespace.
16+ 译者注:如果 return 对象的左括号和 return 不在一行上就会出错。
17+
18+ // 译者注:下面输出 undefined
19+ function add(a, b) {
20+ return
21+ a + b;
22+ }
23+ console.log(add(1, 2));
2124
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 ` .
25+ JavaScript 中没有显式的命名空间定义,这就意味着所有对象都定义在一个* 全局共享* 的命名空间下面。
2526
26- ### The bane of global variables
27+ 每次引用一个变量,JavaScript 会向上遍历整个作用域直到找到这个变量为止。
28+ 如果到达全局作用域但是这个变量仍未找到,则会抛出 ` ReferenceError ` 异常。
29+
30+ ### 隐式的全局变量(The bane of global variables)
2731
2832 // script A
2933 foo = '42';
3034
3135 // script B
3236 var foo = '42'
3337
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.
38+ 上面两段脚本效果** 不同** 。脚本 A 在* 全局* 作用域内定义了变量 ` foo ` ,而脚本 B 在* 当前* 作用域内定义变量 ` foo ` 。
3739
38- Again, that is ** not** at all the * same effect* , not using ` var ` can have major
39- implications.
40+ 再次强调,上面的效果** 完全不同** ,不使用 ` var ` 声明变量将会导致隐式的全局变量产生。
4041
41- // global scope
42+ // 全局作用域
4243 var foo = 42;
4344 function test() {
44- // local scope
45+ // 局部作用域
4546 foo = 21;
4647 }
4748 test();
4849 foo; // 21
4950
50- Leaving out the ` var ` statement inside the function ` test ` will override the
51- value of ` foo ` . While this might not seem like a big deal at first, having
52- thousands of lines of JavaScript and not using ` var ` will introduce horrible and
53- hard to track down bugs.
51+ 在函数 ` test ` 内不使用 ` var ` 关键字声明 ` foo ` 变量将会覆盖外部的同名变量。
52+ 起初这看起来并不是大问题,但是当有成千上万行代码时,不使用 ` var ` 声明变量将会带来难以跟踪的 BUG。
5453
55- // global scope
54+ // 全局作用域
5655 var items = [ /* some list * /] ;
5756 for(var i = 0; i < 10; i++) {
5857 subLoop();
5958 }
6059
6160 function subLoop() {
62- // scope of subLoop
63- for(i = 0; i < 10; i++) { // missing var statement
61+ // subLoop 函数作用域
62+ for(i = 0; i < 10; i++) { // 没有使用 var 声明变量
6463 // do amazing stuff!
6564 }
6665 }
67-
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.
7266
73- ### Local variables
67+ 外部循环在第一次调用 ` subLoop ` 之后就会终止,因为 ` subLoop ` 覆盖了全局变量 ` i ` 。
68+ 在第二个 ` for ` 循环中使用 ` var ` 声明变量可以避免这种错误。
69+ 声明变量时** 绝对不要** 遗漏 ` var ` 关键字,除非这就是* 期望* 的影响外部作用域的行为。
70+
71+ ### 局部变量(Local variables)
7472
75- The only source for local variables in JavaScript are
76- [ function] ( #function.general ) parameters and variables that were declared via the
77- ` var ` statement.
73+ JavaScript 中局部变量只可能通过两种方式声明,一个是作为[ 函数] ( #functions ) 参数,另一个是通过 ` var ` 关键字声明。
7874
79- // global scope
75+ // 全局变量
8076 var foo = 1;
8177 var bar = 2;
8278 var i = 2;
8379
8480 function test(i) {
85- // local scope of the function test
81+ // 函数 test 内的局部作用域
8682 i = 5;
8783
8884 var foo = 3;
8985 bar = 4;
9086 }
9187 test(10);
9288
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.
89+ ` foo ` 和 ` i ` 是函数 ` test ` 内的局部变量,而对 ` bar ` 的赋值将会覆盖全局作用域内的同名变量。
9590
96- ### Hoisting
91+ ### 变量声明提升( Hoisting)
9792
98- JavaScript ** hoists** declarations. This means that both ` var ` statements and
99- ` function ` declarations will be moved to the top of their enclosing scope.
93+ JavaScript 会** 提升** 变量声明。这意味着 ` var ` 表达式和 ` function ` 声明都将会被提升到当前作用域的顶部。
10094
10195 bar();
10296 var bar = function() {};
@@ -115,16 +109,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and
115109 }
116110 }
117111
118- The above code gets transformed before any execution is started. JavaScript moves
119- the ` var ` statements as well as the ` function ` declarations to the top of the
120- nearest surrounding scope.
112+ 上面代码在运行之前将会被转化。JavaScript 将会把 ` var ` 表达式和 ` function ` 声明提升到当前作用域的顶部。
121113
122- // var statements got moved here
123- var bar, someValue; // default to 'undefined'
114+ // var 表达式被移动到这里
115+ var bar, someValue; // 缺省值是 'undefined'
124116
125- // the function declartion got moved up too
117+ // 函数声明也会提升
126118 function test(data) {
127- var goo, i, e; // missing block scope moves these here
119+ var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
128120 if (false) {
129121 goo = 1;
130122
@@ -136,96 +128,93 @@ nearest surrounding scope.
136128 }
137129 }
138130
139- bar(); // fails with a TypeError since bar is still 'undefined'
140- someValue = 42; // assignments are not affected by hoisting
131+ bar(); // 出错: TypeError,因为 bar 依然是 'undefined'
132+ someValue = 42; // 赋值语句不会被提升规则( hoisting)影响
141133 bar = function() {};
142134
143135 test();
144136
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.
137+ 没有块级作用域不仅导致 ` var ` 表达式被从循环内移到外部,而且使一些 ` if ` 表达式更难看懂。
148138
149- In the original code the ` if ` statement seemed to modify the * global
150- variable* ` goo ` , while actually it modifies the * local variable* - after hoisting
151- has been applied.
139+ 在原来代码中,` if ` 表达式看起来修改了* 全部变量* ` goo ` ,实际上在提升规则(hoisting)被应用后,却是在修改* 局部变量* 。
152140
153- Without the knowledge about * hoisting* , below code might seem to raise a
154- ` ReferenceError ` .
141+ 如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常 ` ReferenceError ` 。
155142
156- // check whether SomeImportantThing has been initiliazed
143+ // 检查 SomeImportantThing 是否已经被初始化
157144 if (!SomeImportantThing) {
158145 var SomeImportantThing = {};
159146 }
160147
161- But of course, the above works due to the fact that the ` var ` statement is being
162- moved to the top of the * global scope* .
148+ 实际上,上面的代码正常运行,因为 ` var ` 表达式会被提升到* 全局作用域* 的顶部。
163149
164150 var SomeImportantThing;
165151
166- // other code might initiliaze SomeImportantThing here, or not
152+ // 其它一些代码,可能会初始化 SomeImportantThing,也可能不会
167153
168- // make sure it's there
154+ // 检查是否已经被初始化
169155 if (!SomeImportantThing) {
170156 SomeImportantThing = {};
171157 }
172158
173- ### Name resolution order
159+
160+ 译者注:在 Nettuts+ 网站有一篇介绍 hoisting 的[ 文章] [ 1 ] ,其中的代码很有启发性。
174161
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* .
162+ // 译者注:来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
163+ var myvar = 'my value';
164+
165+ (function() {
166+ alert(myvar); // undefined
167+ var myvar = 'local value';
168+ })();
169+
170+
171+ ### 名称解析顺序(Name resolution order)
177172
178- Function scopes also have the name [ ` arguments ` ] ( #function.arguments ) defined in
179- them which contains the arguments that were passed to a function.
173+ JavaScript 中的所有作用域,包括* 全局作用域* ,都有一个特别的名称 [ ` this ` ] ( #this ) 指向当前对象。
180174
181- For example, when trying to access a variable named ` foo ` inside the scope of a
182- function, JavaScript will lookup the name in the following order:
175+ 函数作用域内也有默认的变量 [ ` arguments ` ] ( #arguments ) ,其中包含了传递到函数中的参数。
183176
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.
177+ 比如,当访问函数内的 ` foo ` 变量时,JavaScript 会按照下面顺序查找:
188178
189- > ** Note:** Having a parameter called ` arguments ` will ** prevent** the creation
190- > of the default ` arguments ` object.
179+ 1 . 当前作用域内是否有 ` var foo ` 的定义。
180+ 2 . 函数形式参数是否有使用 ` foo ` 名称的。
181+ 3 . 函数自身是否叫做 ` foo ` 。
182+ 4 . 回溯到上一级作用域,然后从 ** #1 ** 重新开始。
191183
192- ### Namespaces
184+ > ** 注意: ** 自定义 ` arguments ` 参数将会阻止原生的 ` arguments ` 对象的创建。
193185
194- A common problem of having only one global namespace is the likeliness of running
195- into problems where variable names clash. In JavaScript, this problem can
196- easily be avoided with the help of * anonymous wrappers * .
186+ ### 命名空间(Namespaces)
187+
188+ 只有一个全局作用域导致的常见错误是命名冲突。在 JavaScript中,这可以通过 * 匿名包装器 * 轻松解决。
197189
198190 (function() {
199- // a self contained "namespace"
191+ // 函数创建一个命名空间(译者注:也就是作用域)
200192
201193 window.foo = function() {
202- // an exposed closure
194+ // 对外公开的函数,创建了闭包
203195 };
204196
205- })(); // execute the function immediately
206-
197+ })(); // 立即执行此匿名函数
207198
208- Unnamed functions are considered [ expressions] ( #function.general ) ; so in order to
209- being callable, they must first be evaluated.
199+ 匿名函数被认为是 [ 表达式] ( #functions ) ;因此为了可调用性,它们首先会被执行(evaluated)。
210200
211- ( // evaluate the function inside the paranthesis
201+ ( // 小括号内的函数首先被执行
212202 function() {}
213- ) // and return the function object
214- () // call the result of the evaluation
203+ ) // 并且返回函数对象
204+ () // 调用上面的执行结果,也就是函数对象
215205
216- There are other ways for evaluating and calling the function expression; which,
217- while different in syntax, do behave the exact same way.
206+ 有一些其他的调用函数表达式的方法,比如下面的两种方式语法不同,但是效果一模一样。
218207
219- // Two other ways
208+ // 另外两种方式
220209 +function(){}();
221210 (function(){}());
222211
223- ### In conclusion
212+ ### 结论(In conclusion)
213+
214+ 推荐使用* 匿名包装器* (译者注:也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突,
215+ 而且有利于程序的模块化。
224216
225- It is recommended to always use an * anonymous wrapper* for encapsulating code in
226- its own namespace. This does not only protect code against name clashes, it
227- also allows for better modularization of programs.
217+ 另外,使用全局变量被认为是** 不好的习惯** 。这样的代码倾向于产生错误和带来高的维护成本。
228218
229- Additionally, the use of global variables is considered ** bad practice** . ** Any**
230- use of them indicates badly written code that is prone to errors and hard to maintain.
231219
220+ [ 1 ] : http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/
0 commit comments