javascript 中闭包的例子

闭包含义:

一般函数;
function outer() {
    
    
  var localVal = 30;
  return localVal
}

outer() //30

outer 函数里有一个局部变量 localVal, 值为 30. 然后 return 出去
对于一般函数, 在调用结束后, 实际上局部变量可以释放了.
具体释放要取决于垃圾回收机制
这是一般函数的情况.

但对于 javascript中的函数也是对象,
并且函数也可以作为返回值, 也可以作为传参, 函数里也可以嵌套函数.
实例如下:
function outer() {
    
    
  var localVal = 30;
  return function() {
    
    
    return localVal
  }
}

var func = outer();
func(); //30

outer函数的返回值是一个匿名函数表达式,
在匿名函数里又 return 了 outer 函数的局部变量 localVal,
所以对于一般函数的情况,函数调用返回后局部变量可以被释放.

但是这种嵌套的情况, localVal 不能被释放, 因为调用 outer 之后,
返回的是匿名函数, 匿名函数里面仍然可以访问外部 outer 的局部变量,
那么函数 outer 调用结束之后, 
func 这个函数, 再次调用仍能访问到外函数的局部变量.
这种情况就是闭包.

闭包作用:

闭包的作用:
处理事件点击
处理异步请求
封装变量
等...

比如:
!function() {
    
    
  var localData = "localData here";
  var url = "http://www.baidu.com/";
  $.ajax({
    
    
    url:url,
    success:function() {
    
    
      //do sth.
      console.log(localData)
    }
  })
}

success 的回调函数里用到外层的变量,
因为有闭包的缘故,
最外面匿名函数结束调用之后,
回调函数仍有能力访问到外层的 localData, url 等

封装:
在这里插入图片描述


闭包的小坑:

document.body.innerHTML = "<div id='div1'>aaa</div>" + 
"<div id='div2'>bbb</div>" + 
"<div id='div3'>ccc</div>";
for(var i = 1; i<4;i++) {
    
    
  document.getElementById('div' + i);
  addEventListener('click', function() {
    
    
    alert(i) //all are 4!
  })
}

想实现的效果是点击 aaa 的时候输出 1, 点击 bbb 输出 2, 以此类推;
但是实际上点击任何一个都返回 4.
这就是因为闭包的原因,
addEventListener 是回调函数, 当点击的时候, 这个回调函数才会动态的拿到 i 的值,
但是 i 的值在初始化完成之后已经是 4,
比如在 for 循环外面拿到 i 的值, 是循环最终的结果 i 是 4

如何实现真正想要的效果
改造如下:

document.body.innerHTML = "<div id='div1'>aaa</div>" + 
"<div id='div2'>bbb</div>" + 
"<div id='div3'>ccc</div>";
for(var i = 1; i<4;i++) {
    
    
	!function(i) {
    
    
		  document.getElementById('div' + i);
  			addEventListener('click', function() {
    
    
    		alert(i) //all are 4!
  		})
	}(i);
}

在每一次循环的时候, 用一个匿名函数, 而且是立即执行的匿名函数包装起来,
包装起来之后, 每一次遍历的 i 传到匿名函数里, 在匿名函数里面再用参数 i 来引用使用
这样每次点击对应的 alert 的时候, 这时的 i 都取自每次闭包环境下的 i,
这个 i 来源于每次循环的赋值时候 i

猜你喜欢

转载自blog.csdn.net/m0_48446542/article/details/109018257
今日推荐