词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。 with和eval除外,所以只能说JS的作用域机制非常接近词法作用域(Lexical scope)。
作用域链:词法作用域的实现机制就是作用域链(scopeChain)。作用域链是一套按名称查找(Name Lookup)的机制,首先在当前执行环境的 ActiveObject 中寻找,没找到,则顺着作用域链到父 ActiveObject 中寻找,一直找到全局调用对象(Global Object)
· 变量查找规则是首先在当前执行环境的 ActiveObject 中寻找,没找到,则顺着执行环境中属性 ScopeChain 指向的 ActiveObject 中寻找,一直到 Global Object(window)方法执行完成后,内部变量值不会被重置,至于变量什么时候被销毁,请参考下面一条方法内变量的生存周期取决于方法实例是否存在活动引用,如没有就销毁活动对象
【在一个方法中,同名的实参,形参和变量之间是引用关系,也就是JS引擎的处理是同名变量和形参都引用同一个内存地址】,
经典案例
1. /*全局(window)域下的一段代码*/
2. var i=10;
3. function a(){
4. alert(i);
5. vari = 2;
6. alert(i);
7. };
8. a();
疑问:上面的代码又会输出什么呢?(小子,看这回整不死你!哇哈哈,就不给你选项)
答案:在FireBug中的运行结果是 undefined, 2,下面简单说一下具体执行过程
1. 第一个alert输出undefined
2. 第二个alert输出 2
3. 思考:到底怎么回事儿?
根据【JS引擎变量查找规则,首先在当前执行环境的 ActiveObject 中寻找,没找到,则顺着执行环境中属性 ScopeChain 指向的 ActiveObject 中寻找,一直到 Global Object(window)】,所以在案例中,因为在当前的ActiveObject中找到了有变量 i 的定义,只是值为 “undefined”,所以直接输出 “undefined” 了
[javascript] view plain copy
1. <pre name="code" class="javascript"> <pre name="code" class="javascript" style="font-weight: bold;"> var name = "Andyfu";<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
[javascript] view plain copy
1. function init() {
2.
3.
4. function displayName() {
5. alert(name);
6. };
7. var name = "Mozila";
8. displayName();
9. }
10. init();//Mosila
[javascript] view plain copy
1. var name = "Andyfu";
2.
3. function init() {
4. function displayName() {
5. alert(name);
6. };
7. displayName();
8. var name = "Mozila";
9. }
10. init(); //undefined
[javascript] view plain copy
1. var name = "Andyfu";
2. function init() {
3. function displayName() {
4. alert(name);
5. };
6. displayName();
7. name = "Mozila";
8. }
9. init(); //Andyfu
[javascript] view plain copy
1. var name = "Andyfu";
2.
3. function init() {
4. function displayName() {
5. alert(name);
6. };
7.
8. name = "Mozila";
9. displayName();
10. }
11. init(); //Mozila
[javascript] view plain copy
1. var name = "Andyfu";
[javascript] view plain copy
1. init {
2. (function() {
3. alert(name);
4. })();<span style="font-family: Arial, Helvetica, sans-serif;">//自执行函数</span>
5. var name = "Mozila";
6.
7. }
8. init(); //undefined
[javascript] view plain copy
1. var name = "Andyfu";
2.
3. function init() {
4. (function() {
5. alert(name);
6. })();//自执行函数
7.
8. name = "Mozila";
9.
10. }
11. init(); //Andyfu
[javascript] view plain copy
1. var a = 10;
2.
3. function test() {
4. a = 100;
5. alert(a);
6. alert(this.a); //这里的this还是指向window,但 a = 100和var a这两句相当于var a=100
7. var a;
8. alert(a);
9. }
10. test();//100 10 100
[javascript] view plain copy
1. var a = 10;
2.
3. function test() {
4. a = 100;
5. alert(a);
11. alert(this.a); //这里的this还是指向window,但全局的 a = 100也是指向window,把var a=10 结果覆盖
6.
7. //var a;
8. alert(a);
9. }
10. test();//100 100 100
[javascript] view plain copy
1. var a = 10;
2. alert(this.a);
3. a=50;
4. function test() {
5. a = 100;
6. alert(a);
12. alert(this.a); //这里 a = 100和var a这两句相当于var a=100是局部的,但是a=50,是全局的
7.
8. var a;
9. alert(a);
10. }
11. test();//10 100 50 100