JavaScript闭包

闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。 闭包是 JavaScript 语言的一大特点,主要应用闭包场合主要是为了:设计私有的方法和变量。

闭包的几种表现形式

  1. 返回一个函数
  2. 作为函数参数传递
  3. 回调函数
  4. 非典型闭包IIFE(立即执行函数表达式)

返回一个函数:这种形式的闭包在JavaScript的代码编写中,是非常常见的一种方式。

var a  = 1;
function foo(){
  var a = 2;
  // 这就是闭包
  return function(){
    console.log(a);
  }
}
var bar = foo();
// 输出2,而不是1
bar();

作为函数参数传递:无论通过何种手段将内部函数传递到它所在词法作用域之外,它都会持有对原始作用域的引用,无论在何处执行这个函数,都会产生闭包。

var a = 1;
function foo(){
  var a = 2;
  function baz(){
    console.log(a);
  }
  bar(baz);
}
function bar(fn){
  // 这就是闭包
  fn();
}
// 输出2,而不是1
foo();

回调函数:在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就是在使用闭包。

// 定时器
setTimeout(function timeHandler(){
  console.log('timer');
},100)

// 事件监听
$('#container').click(function(){
  console.log('DOM Listener');
})

IIFE:IIFE(立即执行函数表达式)并不是一个典型的闭包,但它确实创建了一个闭包。

var a = 2;
(function IIFE(){
  // 输出2
  console.log(a);
})();

经典循环和闭包面试题

以下代码运行结果是什么,如何改进?
for(var i=1;i<=5;i++){
  setTimeout(function timer(){
    console.log(i)
  }, i*1000)
}

代码分析

  1. for循环创建了5个定时器,并且定时器是在循环结束后才开始执行
  2. for循环结束后,用var i定义的变量i此时等于6
  3. 依次执行五个定时器,都打印变量i,所以结果是打印5次6

第一种改进方法:利用IIFE(立即执行函数表达式)当每次for循环时,把此时的i变量传递到定时器中

for(var i=1;i<=5;i++){
  (function(j){
    setTimeout(function timer(){
      console.log(j)
    }, i*1000)
  })(i)
}

第二种方法setTimeout函数的第三个参数,可以作为定时器执行时的变量进行使用

for(var i=1;i<=5;i++){
  setTimeout(function timer(j){
    console.log(j)
  }, i*1000, i)
}

第三种方法(推荐):在循环中使用let i代替var i

for(let i=1;i<=5;i++){
  setTimeout(function timer(){
    console.log(i)
  }, i*1000)
}

如若转载,请注明出处:开源字节   https://sourcebyte.cn/article/144.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

开源字节

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

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

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

打赏作者

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

抵扣说明:

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

余额充值