作用域的定义:
作用域分为全局作用域和函数作用域,根据不同执行环境,所包含的变量可访问性也不所不同,也就是变量的可访问范围,全局作用域>函数作用域。
全局作用域:最外围的执行环境,如:js中window对象下的变量、方法、属性,nodejs中global对象都是属于全局作用域
优点:任何一个地方都可以访问
缺点:环境污染(下面会讲到。)
函数作用域:仅在定义的函数下定义的变量可访问
优点:仅在函数下使用,不会被污染
缺点:不能反复使用
<script>
var a = 1;
b = 2;
function fn(e) {
c = 3;
var d = 4;
console.log("a2======",a); // 1
console.log("b2======",b); // 2
console.log("c2======",c); // 3
console.log("d2======",d); // 4
console.log("e2======",e); // 5
}
fn(5);
console.log("a======",a); // 1
console.log("b======",b); // 2
console.log("c======",c); // 3
console.log("d======",d); // d is not defined
console.log("e======",e); // e is not defined
</script>
综上所述,fn内执行的是函数作用域,a、b、c、d、e都能获取到值,在全局环境下,只有d和e报错,但c在fn函数下也能获取到值。
这是因为c没有使用var定义,js在执行中,c赋给了全局的window对象,所以在任何一个地方都能够获取到值,d由于var定义,e作为形参也属于函数作用域下的变量,没有赋给window对象,仅仅在fn函数下才能够获取访问。
说一下全局作用域下环境污染的问题。
函数会有一个生命周期,从开始创建到调用执行结束的一个过程即为函数声明周期,在函数作用域下定义的变量,当函数被执行完之后都会被释放掉,这也是d在全局环境下会报错的原因。
但在全局作用域下,包括函数内没有var声明的c也属于全局作用域的变量,不会被释放掉,这就导致了在全局作用域下,一直保留了c占用着内存,环境污染。
作用域链:
当获取访问某个对象或者变量时,都会从当前作用域下查找,如果找不到就会向上一级作用域查找,直到全局作用域,这个查找的过程形成的链条就是作用域链,当通过作用域链查找时,没有找到的话,就会抛出未定义的异常。
比如:d在fn函数下开始在当前作用域下查找,找到了就打印出了4,当在全局作用域下打印时,开始在当前作用域下没有找到,又因为是全局作用域,没有了上一级的作用域,所以抛出了未定义的异常。