什么是作用域?
作用域是变量与函数的可访问范围。它们是以函数块来划分,每个函数就是一个作用域。
局部作用域
在函数里面声明的变量或者函数是局部作用域,它们只能在声明的函数里面使用,在外面是访问不到的。
1 function fn(){2 var a=10;3 function fn1(){4 console.log('hello');5 }6 }7 console.log(a);//a is not defined8 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 4
如果一个变量没有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);//311 }12 fn1();13 console.log(a);//5
预解析
变量与函数都会有一个解析过程,在作用域中会提前把带有var和function关键字的事先声明,解析到当前作用域的最开始的位置,然后再从上到下执行js语句。
通过var关键字定义的变量或函数进行预解析的时候都只是声明,不管它有没有赋值,都会先赋一个undefined值。
1 console.log(a);//undefined2 var a=1;3 console.log(b);//undefined4 var b;5 console.log(c);//undefined6 var c=function(){7 alert(1);8 }
预解析只会发生在通过var定义的变量和function定义的函数上。
注意:函数表达式的函数体是不会被预解析的,所以不能在声明前去调用。
1 fn();//fn is not defined2 abc();//undefined is not a function3 var abc=function fn(){4 console.log(1);5 };