首页 > 技术文章 > 作用域

imguo 2016-08-12 14:48 原文

什么是作用域?

作用域是变量与函数的可访问范围。它们是以函数块来划分,每个函数就是一个作用域。

局部作用域

在函数里面声明的变量或者函数是局部作用域,它们只能在声明的函数里面使用,在外面是访问不到的。

1 function fn(){
2     var a=10;
3     function fn1(){
4         console.log('hello');
5     }
6 }
7 console.log(a);//a is not defined
8 console.log(fn1());//fn1 is not defined

因为函数可以嵌套函数,在函数内部声明的变量与函数,它的子函数是可以访问到的。

1 function fn(){
2     var a=10;
3     function fn1(){
4         console.log(a);//10 子函数可以访问到父函数的变量
5     }
6     fn1();
7 }
8 fn();

全局作用域

在函数外面声明的变量或者函数就是全局作用域,它们在任何地方都是可以访问到的(包括script标签对)。

1 <script>
2     var a=10;
3 </script>
4 <script>
5     console.log(a);//10
6 </script>

如果一个变量没有var而直接赋值,那不管它是在函数内部还是在函数外声明,它都具有全局作用,在任何地方都可以访问到。声明变量的时候,一定要加var,尽量避免使用全局变量。

1 function fn(){
2     c=100;
3 }
4 fn();
5 console.log(c);//100

所有的全局变量都是window的属性。

作用域链

作用域链是变量与函数的查找规则,函数要找到一个变量,首先他会找自己内部有没有这个变量,如果自己内部有这个变量,它就会取这个变量的值。如果没有,它就会一层一层的往外找,直到找到为止。如果外面也没有,就会报错。

 1 var a=5;
 2 function fn1(){
 3     var a=3;
 4     function fn2(){
 5         console.log(a);//undefined
 6         var a=2;
 7         console.log(a);//2
 8     }
 9     fn2();
10     console.log(a);//3
11 }
12 fn1();
13 console.log(a);//5

预解析

变量与函数都会有一个解析过程,在作用域中会提前把带有var和function关键字的事先声明,解析到当前作用域的最开始的位置,然后再从上到下执行js语句。

通过var关键字定义的变量或函数进行预解析的时候都只是声明,不管它有没有赋值,都会先赋一个undefined值。

1 console.log(a);//undefined
2 var a=1;
3 console.log(b);//undefined
4 var b;
5 console.log(c);//undefined
6 var c=function(){
7     alert(1);
8 }

预解析只会发生在通过var定义的变量和function定义的函数上。

注意:函数表达式的函数体是不会被预解析的,所以不能在声明前去调用。

1 fn();//fn is not defined
2 abc();//undefined is not a function
3 var abc=function fn(){
4     console.log(1);
5 };

 

推荐阅读