写点什么

JavaScript 闭包

作者:源字节1号
  • 2022 年 5 月 31 日
  • 本文字数:1034 字

    阅读完需:约 3 分钟

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,而不是1bar();
复制代码

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

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

回调函数:在定时器、事件监听、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

用户头像

源字节1号

关注

一个着迷于技术又喜欢不断折腾的技术活跃者 2022.03.09 加入

一个着迷于技术又喜欢不断折腾的技术活跃者。喜欢并热爱编程,执着于努力之后所带来的美好生活!

评论

发布
暂无评论
JavaScript闭包_软件开发_源字节1号_InfoQ写作社区