JS 函数作用域和全局作用域

谈到作用域,我们就能想到全局变量、局部变量等名词,接下来,我讲谈谈我对作用域的理解。

ES5中的作用域

ES5中,有两种作用域:函数作用域和全局作用域

第一段代码:

vara =0;  func();functionfunc(){varb =1;    console.log(a);//0 函数作用域中访问全局变量console.log(b);//1}  console.log(b);//报错 全局作用域中访问func函数作用域中的局部变


上面代码中,有两种作用域。全局变量a存在于全局作用域中,而变量b则存在于函数func()所在的函数作用域中,也就是局部变量。 

1. 当我们在函数作用域中访问变量a时,在func函数这个作用域中找不到变量a时,会继续往全局作用域找,因此在函数作用域中访问变量a时实际上是访问的全局变量a,所以console的结果是0。 

2. 如果在函数func中访问不存在的变量c,在func这个函数作用域中找不到,然后继续往全局作用域找,还是找不到变量c,然后就报错。 

3. 当我们在全局作用域访问func函数中的局部变量b时,由于已经处在全局这个大作用域中,再全局作用域中找不到变量b,而全局作用域又叫顶级作用域,因此无法继续往上查找,结果就是直接报错。

我们可以将全局作用域和函数作用域之间的关系理解为父与子,func函数作用存在于全局作用域中,相当于儿子。当儿子没有某个东西的时候,就会找父亲要,如果父亲也没有,那就报错,而父亲是不会找儿子要东西的,这个东西就是js中的变量。js在查找变量时,都是从下级作用域往上级作用域查找的,如果一直到顶级作用域(全局作用域)都没找到,则报错。上面代码中的作用域,可以通过下图来加深理解:

第二段代码:

vari =1;functionfn1(){vari =5;varj =20functionfn2(){vari =10;functionfn3(){varj =15;        console.log(i);//10}      fn3();      console.log(i);//10console.log(j);//20}    fn2();  }  fn1();  console.log(i);//1

首先,我们先看下上面的代码有多少个作用域:全局作用域、fn1函数作用域、fn2函数作用域、fn3函数作用域。 

然后,我们再来看一下每一次console获取的值是怎么查找的。这里我就直接用图来表示了,如果不懂可以看前面的文字描述。 

我们再在控制台中印证一下上面代码的运行结果: 

ES6在ES5的基础上新增了块级作用域

前面提到,es5中只有两种作用域:函数作用域和全局作用域,而es6又新增了一种作用域:块级作用域,即{ }括号形成的作用域。

es5代码片段:

vara=0;if(a<10){a++;var b =a;}console.log(b); //1  b是全局变量。处于全局作用域,会成为全局对象window对象的属性

以上代码,虽然b是在if代码块中定义的,但由于ES5只有全局作用域和函数作用域,没有块级作用域,而b变量不是在函数中定义的,所以b只能是全局变量。

es6代码片段:

leta =0;//注意:使用'let声明的全局变量不会成为window对象的属性if(a <10){    a++;letb = a;}console.log(b);//报错 b是if代码块中的变量,只在'if'代码块{}中生效。处于块级作用域。

ES6中{ }会形成一个块级作用域,所以上面代码的b处于if这个块作用域中,不属于全局作用域。

你可能感兴趣的:(JS 函数作用域和全局作用域)