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

目录

 

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

延伸函数环境生命周期

块作用域


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

es6:
   
 块作用域

 

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

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

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

 

 

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

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

栗子:

<script>
  window.onload = function () {
    function show() {
      var name = 'liang';

      function hd() {
        var age = '18';
      }
      hd();
    }
    show();
  };
</script>

这里画个图示意:

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


 

延伸函数环境生命周期

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

栗子:

<script>
  window.onload = function () {
    function show() {
      var n = 1;

      function sum() {
        console.log(++n);
      }
      sum();
    }
    show();
    show();
    show();
    show();
  };
</script>

                   控制台输出4个2,原因就是因为每次调用函数都是新的环境、新的内存空间、新的数据

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

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

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

<script>
  window.onload = function () {
    function show() {
      var n = 1;

      return function sum() {
        console.log(++n);
      }
      sum();
    }
    let a = show();
    a();
    a();
    a();
  };
</script>

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

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

运行结果:

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

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

运行结果:

 

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

 

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

<script>
  window.onload = function () {
    function show() {
      var n = 1;

      return function sum() {
        let m = 1;

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

  };
</script>

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

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

 

解决:

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

  运行结果:。n也可累加输出

 

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

<script>
  window.onload = function () {
    function Lee() {
      let n = 1;

      function sum() {
        console.log(++n);
      }
      return {
        sum: sum
      };
    }
    let a = new Lee();
    a.sum();
    a.sum();

  };
</script>

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

 


 

 

块作用域

栗子:

<script>
  {
    let a = 1;
  }
  {
    let a = 2;
  }
</script>

画个图:

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

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

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

 

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


 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梁什么鸭,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值