全局作用域、局部作用域、块作用域

目录

 

全局环境和局部环境,全局作用域和局部作用域

延伸函数环境生命周期

块作用域


es5:  
     全局作用域  -->  script  独立JS文件
     函数作用域   -->  

es6:
   
 块作用域

 

无论在什么作用域下,只要没有声明就使用赋值得变量  (a=1;),会成为类似全局作用域得变量的存在

没有声明就赋值的变量会泄露,成为顶层/全局window对象的属性,在任何作用域都能访问到

var声明的全局变量会污染顶层对象的属性环境,即成为window的属性

 

 

全局环境和局部环境,全局作用域和局部作用域

全局环境是不会被卸载掉的,除非把浏览器关闭,或者把标签关了(人为回收了)

栗子:

这里画个图示意:

全局作用域、局部作用域、块作用域_第1张图片

不调用函数就不会开辟出内存空间,此时只是声明了函数,就像盖房,只是画了一个房子设计图,但还没动工,只是个计划,所以还没有开辟一块地开始建房。


 

延伸函数环境生命周期

每次调用函数都会开辟出新的一块内存空间,就像王者荣耀,每开一局都是新的一把游戏,跟上一把游戏没有关系。

栗子:

全局作用域、局部作用域、块作用域_第2张图片                全局作用域、局部作用域、块作用域_第3张图片   控制台输出4个2,原因就是因为每次调用函数都是新的环境、新的内存空间、新的数据

解决的唯一方法:就是把show()环境的数据保留

因为每次调用函数都与上一次调用没有关系,上一次调用函数后的数据,以后都再也不会用到,不用就会被清除掉(原理可参考JS高级程序涉及第4版第94页

那么如果调用后的函数数据一直有被用到,那么就会保留。不只是被用到的数据会被保留,整个环境中的数据都会被保留

return 里返回的其实是匿名函数,但为了方便理解,这里还是设置了函数名。

这里不可以返回n, 因返回n只是把值返回到外部

运行结果:

全局作用域、局部作用域、块作用域_第4张图片

若复制给一个新的变量b ,函数show()再一次被调用,那么数据就又是新的一批数据

 let a = show();
    a();
    a();
    a();
 let b = show();
    b();
    b();

运行结果:全局作用域、局部作用域、块作用域_第5张图片

 

可以这样理解:
每赋值给一个新的变量,相当于调用一次show函数,就会开辟出新的一个内存环境,每个环境都是无关的,独立的,重新加载的数据
每调用一次被赋值的变量函数,相当于在当前环境,即当前数据基础上执行

全局作用域、局部作用域、块作用域_第6张图片

 

接下来讨论另一种情况,栗子:

那么此时会进行累加操作吗??

答案是不会。   。原因是因为当lee函数执行完之后,lee()里的数据就被清除掉了,数据没有被保留。sum()函数还是会被反复创建,跟前面是一个道理

全局作用域、局部作用域、块作用域_第7张图片

 

解决:

 return function lee() {
          console.log(++m);
        };
      };
    }
    let a = show()();
    a();
    a();

全局作用域、局部作用域、块作用域_第8张图片  运行结果:。n也可累加输出

 

那么构造函数如何实现以上内容呢?

运行结果:     每new一个对象,都调用一次Lee构造函数,原理跟上面相同

 


 

 

块作用域

栗子:

画个图:

全局作用域、局部作用域、块作用域_第9张图片

两个块,虽然名字相同,但是不同的数据,把不同的环境,不同的作用域存在的。所以可设置相同名。

在同环境,作用域中是不可以设置相同名的变量或函数的

a在外部不可以使用,会显示a is not defined错误
用var会把a放在全局作用域中,因为var没有块级作用域,但有函数作用域。
因为var历史比较早,块级作用域是在var后面推出的,为了考虑兼容性,就没把var纳入到块级作用域中,而推出了let和const

 

用法:需要开辟一个新的作用域,而这块作用域不需要重复调用,只需要执行一次,就用块作用域,但块作用域只能用let,不能用var。不污染全局环境


 

 

 

你可能感兴趣的:(Javascript,javascript)