上一篇文章中简单介绍了一下JS作用域,本篇将作进一步探究和总结。
前言:JavaScript的作用域一直以来都是前端开发中比较难以理解的知识点,JavaScript6中新引入了 let 关键字,用于指定变量属于块级作用域,本次先忽略这个点。
很多语言如c#,java都是以代码块作为作用域即大括号也是一个作用域,JavaScript却是以函数作为作用域,如果你对python比较了解,理解起来应该很easy。
在c#中下面的代码将直接报错:
1 public void Func(){
2 if(1==1){
3 string name = 'Java';
4
5 }
6 console.writeline(name);
7
8 }
9 Func()
10 // 报错
在JavaScript语言中无块级作用域:
1 function Main(){
2 if(1==1){
3 var name = 'seven';
4 }
5 console.log(name);
6 }
7 // 输出: seven
我们先来回忆一下python的作用域(如果不会python可以跳过,不影响后面阅读):
1 # 情况一:
2 def func():
3 if 1 == 1:
4 name = 'alex'
5 print(name)
6 func()
7 # 成功
8
9 # 情况二:
10 def func():
11 if 1 == 1:
12 name = 'alex'
13 print(name)
14
15 func()
16 print(name)
17 # // 报错
再来看看JavaScript采用函数作用域:
1 function Main(){
2 var innerValue = 'seven';
3 }
4
5 Main();
6
7 console.log(innerValue);
8
9 // 报错:Uncaught ReferenceError: innerValue is not defined
在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。console.log(innerValue)访问函数Main()中的变量肯定是不行的。
在JavaScript中如果不创建(声明)变量,直接去使用,则报错:
1 console.log(x);
2 VM199:1 Uncaught ReferenceError: x is not defined(…)
JavaScript中如果创建值而不赋值,则该值为 undefined,如:
1 var num;
2 console.log(num);
3
4 //undefined
了解了这个看看下面这个函数:
1 function func(){
2 if(1==1){
3 var name = 'alex';
4 }
5 console.log(name);
6 }
在浏览器中直接输入这个函数会得到undefined,而不是报错,就说明变量name在函数调用之前就创建(声明)了,但没有被赋值。
1 1 <script>
2 2 x = "alex";
3 3 function func() {
4 4 var x = "eric";
5 5 function inner() {
6 6 var x = "tony";
7 7 console.log(x);
8 8 }
9 9 inner();
10 10 }
11 11 func();
12 12 </script>
输出结果是tony。
如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:
当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。
练习题1:
1 x = "alex";
2 function func() {
3 var x = "eric";
4 function inner() {
5 console.log(x);
6 }
7 return inner;
8 }
9 var res = func();
10 res();
结果:eric
上述代码,在函数被调用之前作用域链已经存在:
当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。
练习题2:
1 x = "alex";
2 function func() {
3 var x = "eric";
4 function inner() {
5 console.log(x);
6 }
7 var x = 'tony';
8 return inner;
9 }
10 var res = func();
11 res();
结果:tony
1 function func(){
2 console.log(xo);
3 var xo = 'alex';
4 }
5
6 func();
7 // undefined
上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。