Javascript 作用域

1:函数在未执行前,内部代码不执行

2: javascript中,变量的作用域是函数。 不是代码块

 

下面的代码中,在一开始编译的时候,会将代码“执行”一次,这个时候变量i的变量已经经过循环变化为了3。但是function并没有执行。

 

在执行内部function的时候,会现在内部寻找i,因为function内部没有i,所以开始向上寻找。在外部的func找到i,此时i为3。所以下面的代码, 在执行的时候,会一直打印3。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 
 7 
 8 </head>
 9 <body>
10 <script>
11     function func(){
12         for(var i=0; i<3;i++){
13             setInterval(function(){
14                 console.log(i)
15             },1000);
16     }
17     }
18 
19 
20     func();
21 </script>
22 </body>
23 </html>

 

 

样例二:

 下面的例子中,将样例1 setinterval的部分,修改为了自执行函数。所以在一开始解释的时候,就会去执行。输出1,2,3

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 
 7 
 8 </head>
 9 <body>
10 <script>
11     function func(){
12         for(var i=0; i<3;i++){
13             setInterval((function(arg){
14                 console.log(arg)
15             })(i),1000);
16     }
17     }
18 
19 
20     func();
21 </script>
22 </body>
23 </html>

 

3:javascript的作用域链。如果有嵌套函数,就会出现嵌套作用域链条。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <script>
 9     xo = 'alex';
10   
11 function Func(){
12     var xo = "seven";
13     function inner(){
14         var xo = 'alvin';
15         console.log(xo);
16     }
17     inner();
18 }
19 Func();
20 </script>
21 </body>
22 </html>

 

如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:

当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。

如果注释掉 alvin,将会打印 seven,如果注释掉seven,将会打印 alex

 

 

4:作用域在执行前已经存在

样例一:

JavaScript的作用域在被执行之前已经创建,日后再去执行时只需要按照作用域链去寻找即可。

 1 xo = 'alex';
 2  
 3 function Func(){
 4     var xo = "seven";
 5     function inner(){
 6  
 7         console.log(xo);
 8     }
 9     return inner;
10 }
11  
12 var ret = Func();
13 ret();
14 // 输出结果: seven

上述代码,在函数被调用之前作用域链已经存在:

  • 全局作用域 -> Func函数作用域 -> inner函数作用域

当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。

 

样例二:

 1 xo = 'alex';
 2  
 3 function Func(){
 4     var xo = "eirc";
 5     function inner(){
 6  
 7         console.log(xo);
 8     }
 9     xo = 'seven';
10     return inner;
11 }
12  
13 var ret = Func();
14 ret();
15 // 输出结果: seven

上述代码和示例一的目的相同,也是强调在函数被调用之前作用域链已经存在:

  • 全局作用域 -> Func函数作用域 -> inner函数作用域

不同的时,在执行【var ret = Func();】时,Func作用域中的xo变量的值已经由 “eric” 被重置为 “seven”,所以之后再执行【ret();】时,就只能找到“seven”。

 

样例三:

 1 <script>
 2  xo = 'alex';
 3 function Bar(){
 4     console.log(xo);
 5 }
 6 
 7 function Func(){
 8     var xo = "seven";
 9 
10     return Bar;
11 }
12 
13 var ret = Func();
14 ret();
15 // 输出结果: alex
16 </script>

上述代码,在函数被执行之前已经创建了两条作用域链:

  • 全局作用域 -> Bar函数作用域
  • 全局作用域 -> Func函数作用域

当执行【ret();】时,ret代指的Bar函数,而Bar函数的作用域链已经存在:全局作用域 -> Bar函数作用域,所以,执行时会根据已经存在的作用域链去寻找。

 

5:提前声明

在JavaScript中如果不创建变量,直接去使用,则报错:

1 console.log(xxoo);
2 // 报错:Uncaught ReferenceError: xxoo is not define

JavaScript中如果创建值而不赋值,则该值为 undefined,如:

1 var xxoo;
2 console.log(xxoo);
3 // 输出:undefined
 
内如果这么写:
1 function Foo(){
2     console.log(xo);
3     var xo = 'seven';
4 }
5  
6 Foo();
7 // 输出:undefined

上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。

posted @ 2016-08-13 16:31  咖啡茶  阅读(98)  评论(0)    收藏  举报