函数的闭包、作用域链、执行环境及作用域

函数闭包
1、什么是闭包函数?
有权访问另一个函数作用域中变量的函数
比如:

function a () { var aaa=123};
function b () {console.log(aaa)};
b();//aaa is not defined 此时aaa是b访问不到的变量

//我换种写法
function a () { var aaa=123 ; 
function b () {console.log(aaa)}; b();};
a();//123  此时b就可以访问到a的变量,这就是创建闭包的常见方式

2、函数的作用域链
用途:保证变量和函数的有序访问
当函数被调用时,会创建一个执行环境和相应的作用域链。使用arguments和其他命名参数的值来初始化活动对象。

函数执行过程中,需要读取和写入变量,就需要在作用域链中查找变量。
在作用域链中,外部函数的活动对象始终处于第二位,依次类推。
比如:上面例子中,b函数首先在自己的作用域中寻找aaa变量,找不到再去外部函数a的作用域寻找aaa,找到了就停止查找,找不到,再往外去查找,依次类推。
再举个例子:`

var aaa=456;
function a () { var aaa=123 ; 
function b () {console.log(aaa)}; b();};
a();

这个例子最后打印出来是?
这是结果
所以在查找到外部函数变量a的时候找到aaa这个变量,查找停止,不会访问全局变量aaa了。
3、执行环境及作用域
定义了变量和函数有权访问的其他数据,决定他们各自的行为。
每个执行环境都有一个与之关联的变量对象,环境中定义的函数及变量都保存在这个对象中。
每个函数都有自己的执行环境
可以分成两种:全局执行环境、函数执行环境
比如:在执行上面例子的代码时
在这里插入图片描述
此时全局的执行环境是这样的
在这里插入图片描述
当执行流进入一个函数时,函数环境会被推入一个环境栈
也就是说,当调用函数a的时,a的执行环境会被推入环境栈
在这里插入图片描述
但是a函数里面还有一个函数,那就继续推进环境栈。
在这里插入图片描述
环境战中的变量对象,从上到下组成一个作用域链,这样就可以有序的访问变量啦!
总结:**函数被创建时会创建一个预先包含全局变量对象的作用域链,这个作用域链被保存在内部的[[scope]]属性中。
函数被调用时会为函数创建一个执行环境,然后通过这个预先保存的[[scope]]中的对象构建作用域链,依次将需要的变量对象推进环境作用域链前端。
作用域链,本质是指向变量对象的指针。
4、闭包
全局环境的变量对象始终存在
局部环境
的变量只在函数执行的时候存在,执行完成后,环境就会被销毁。
但是闭包的情况有所不同,
还是以上面的例子为例:
当a执行完毕,其执行环境作用域链会被销毁。但是b会把a的变量aaa添加到b的作用域链上,因为b一直引用这个变量,所以,这个变量会留在内存中
解决办法:将函数b销毁,解除对变量的引用
5、闭包与变量
一个很绕的例子,经常能看到这种函数。

function a(){
var aaa = new array();
for (var i=0;i<10;i++){
aaa[i] = function (){
return i}}
return aaa;}

这个例子,表面上看,每个函数都会返回自己的索引值。实际上,返回的都是10.。
原因是—由于作用域链的机制,导致闭包函数只能取得的包含函数变量的最后一个值。
例子中,内部函数的作用域链中都包含,外部函数的变量i,他们引用的都是同一个i,即外部函数的最后一个值10。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值