作用域链、闭包

什么是闭包?

js语言的特点之一是:内部函数可以访问全局变量的值,而外部函数不能访问内部变量的值。

function test()
{
 var a="123";
 function b()
 {
   console.log(a);
 }
 b();
}
test();//输出123
反过来,如果a变量在函数b内部的话,test函数是访问不到的。内层函数实际上可以访问外部的所有变量的值,在函数内部取值的时候,优先从自己的函数块中查找,如果没有,则返回上一层函数从中查找,一直到查到全局变量为止。这样就形成了一个作用域链。
内部函数改变全局变量是否对外部函数有影响?

function a()
{
  var aaa="123";
  function b()
  {
   aaa="456";
   console.log(aaa);//输出456
  }
  b();
  console.log(aaa);//输出456
}
a();
a函数执行时引起b函数的定义,并且执行了b函数,改变了aaa变量的值,两次输出一样,说明是有影响的,内部函数拿到的外部函数的变量应该指向同一个地址。

function a()
{
  function b()
  {
   aaa="456";
   console.log(aaa);//输出456
  }
  b();
  var aaa="123";
  console.log(aaa);//输出123
}
a();
   以上执行的结果会让人误以为内部函数改变了变量的值对外部函数没有影响, 在a函数执行的时候,引起b函数的定义,按理说如果有影响,两次输出应该都是456,因为内部函数改变了aaa的值,但是b函数执行的时候还没有aaa变量,之所以能输出aaa是因为 实际上在js中应该注意的是b函数内部的aaa是一个未申明就赋值的变量,这个时候aaa属于全局变量,归window所有。

什么时候生成闭包?

function a()
{
 var x=100;
 function b()
 {
   x++;
   console.log(x);
 }
 return b;//返回b以后,a的执行期上下文销毁,但是b拿到了a的执行期上下文里面的变量x。
}
var c=a();
c();//101
c();//102
c();//103实际上执行的是b函数,将b函数保存在外面了,每次b执行改变的都是a的执行期上下文里面的变量
  实际上如果将内部函数保存到外部,一定生成了闭包 。c变量存储的是b函数,每次对变量的累加其实改变的都是同一个x

看下面一个例子:

function test()
{
  var arr=[];
  for(var i=0;i<10;i++)
  {
    arr[i]=function ()
	{
	  document.write(i+" ");//输出10个10
	}
  }
  return arr;//test函数执行完毕时,i==10,内层的匿名函数并没有执行而是返回到了外部
}
var t=test();
 for(var j=0;j<10;j++)
 {
   t[j]();//执行匿名函数,这时候找i,自己的函数内部没有,在作用域链上查找,拿到test内部的执行期上下文的变量i,这时i为10
 }
该段代码是一个经典的闭包,本来按正常应该输出1到9,实际上在js中,函数一旦没有执行被保存到外部,就形成了闭包,这段代码中,数组内部先存了10个匿名函数,分别输出i,但是却没有执行,当第二次用for循环执行匿名函数的时候,test函数已经执行完毕,在它的执行期上下文当中存了一个i=10,这个时候每次实际上都是从外层函数的作用域里拿到的变量值。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值