热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScript闭包之经典案例

①函数作为返回值【1】例子1functiona(){varnamedov;returnfunction(){returnname;}}varba();console.log(b(

①函数作为返回值

【1】例子1

function a() {var name='dov';return function(){return name;}}var b=a();console.log(b());//dov

在这段代码中,a()中的返回值是一个匿名函数,这个函数在a()作用域内部,所以它可以获取a()作用域下变量name的值,将这个值作为返回值赋给全局作用域下的变量b,实现了在全局变量下获取到局部变量中的变量的值

【2】例子2

function fn() {var num=3;return function(){var n=0;console.log(++n);console.log(++num);}}var fn1=fn();fn1();//n=1;num=4fn1();//n=1;num=5

一般情况下,在函数fn执行完后,就应该连同它里面的变量一同被销毁,但是在这个例子中,匿名函数作为fn的返回值被赋值给了fn1,这时候相当于fn1=function(){var n = 0 ... },并且匿名函数内部引用着fn里的变量num,所以变量num无法被销毁,而变量n是每次被调用时新创建的,所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁,于是乎最后就剩下孤零零的num,于是这里就产生了内存消耗的问题

【3】定时器与闭包

写一个for循环,让它按顺序打印出当前循环次数

for(var i&#61;0;i<5;&#43;&#43;i){setTimeout(function(){console.log(i&#43;&#39; &#39;)},100)
}

按照预期它应该依次输出1 2 3 4 5&#xff0c;而结果它输出了五次5&#xff0c;这是为什么呢&#xff1f;原来由于js是单线程的&#xff0c;所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行&#xff0c;而在等待过程中for循环就已经在执行&#xff0c;等到setTimeout可以执行的时候&#xff0c;for循环已经结束&#xff0c;i的值也已经编程5&#xff0c;所以打印出来五个5&#xff0c;那么我们为了实现预期结果应该怎么改这段代码呢&#xff1f;&#xff08;ps:如果把for循环里面的var变成let&#xff0c;也能实现预期结果&#xff09;

for (var i &#61; 0; i <5; &#43;&#43;i) {(function (i) {setTimeout(function () {console.log(i &#43; &#39; &#39;)}, 100)}(i))}

引入闭包来保存变量i&#xff0c;将setTimeout放入立即执行函数中&#xff0c;将for循环中的循环值i作为参数传递&#xff0c;100毫秒后同时打印出1 2 3 4 5

那如果我们想实现每隔100毫秒分别依次输出数字&#xff0c;又该怎么改呢?

for (var i &#61; 1; i <5; &#43;&#43;i) {(function (i) {setTimeout(function () {console.log(i &#43; &#39; &#39;)}, 100*i)}(i))}

在这段代码中&#xff0c;相当于同时启动3个定时器&#xff0c;i*100是为4个定时器分别设置了不同的时间&#xff0c;同时启动&#xff0c;但是执行时间不同&#xff0c;每个定时器间隔都是100毫秒&#xff0c;实现了每隔100毫秒就执行一次打印的效果。


②闭包作为参数传递

var num&#61;15;var fn1&#61;function(x){if(x>num){console.log(x)}}void function(fn2){var num&#61;100;fn2(30)}(fn1)//30

在这段代码中&#xff0c;函数fn1作为参数传入立即执行函数中&#xff0c;在执行到fn2(30)的时候&#xff0c;30作为参数传入fn1中&#xff0c;这时候if(x>num)中的num取的并不是立即执行函数中的num&#xff0c;而是取创建函数的作用域中的num这里函数创建的作用域是全局作用域下&#xff0c;所以num取的是全局作用域中的值15&#xff0c;即30>15&#xff0c;打印30


最后总结一下闭包的好处与坏处

好处

①保护函数内的变量安全 &#xff0c;实现封装&#xff0c;防止变量流入其他环境发生命名冲突

②在内存中维持一个变量&#xff0c;可以做缓存&#xff08;但使用多了同时也是一项缺点&#xff0c;消耗内存&#xff09;

③匿名自执行函数可以减少内存消耗

坏处

①其中一点上面已经有体现了&#xff0c;就是被引用的私有变量不能被销毁&#xff0c;增大了内存消耗&#xff0c;造成内存泄漏&#xff0c;解决方法是可以在使用完变量后手动为它赋值为null&#xff1b;

②其次由于闭包涉及跨域访问&#xff0c;所以会导致性能损失&#xff0c;我们可以通过把跨作用域变量存储在局部变量中&#xff0c;然后直接访问局部变量&#xff0c;来减轻对执行速度的影响

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 在PHP中如何正确调用JavaScript变量及定义PHP变量的方法详解 ... [详细]
  • 技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统
    技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统 ... [详细]
  • 利用 JavaScript 和 Node.js 验证时间的有效性
    本文探讨了如何使用 JavaScript 和 Node.js 验证时间的有效性。通过编写一个 `isTime` 函数,我们可以确保输入的时间格式正确且有效。该函数利用正则表达式匹配时间字符串,检查其是否符合常见的日期时间格式,如 `YYYY-MM-DD` 或 `HH:MM:SS`。此外,我们还介绍了如何处理不同时间格式的转换和验证,以提高代码的健壮性和可靠性。 ... [详细]
  • 全面解析JavaScript代码注释技巧与标准规范
    在Web前端开发中,JavaScript代码的可读性和维护性至关重要。本文将详细介绍如何有效地使用注释来提高代码的可读性,并探讨JavaScript代码注释的最佳实践和标准规范。通过合理的注释,开发者可以更好地理解和维护复杂的代码逻辑,提升团队协作效率。 ... [详细]
  • 深入解析JavaScript柯里化的实现机制及其应用场景
    本文深入探讨了JavaScript中柯里化的实现机制及其应用场景。通过详细的示例代码,文章全面解析了柯里化的工作原理和实际应用,为读者提供了宝贵的学习资源,有助于提升编程技能和解决实际开发中的问题。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
  • 本文详细探讨了使用纯JavaScript开发经典贪吃蛇游戏的技术细节和实现方法。通过具体的代码示例,深入解析了游戏逻辑、动画效果及用户交互的实现过程,为开发者提供了宝贵的参考和实践经验。 ... [详细]
  • 本文详细探讨了JavaScript中数组去重的各种方法,并通过实际代码示例进行了深入解析。文章首先介绍了几种常见的去重技术,包括使用Set对象、过滤方法和双重循环等。每种方法都附有具体的实现代码,帮助读者更好地理解和应用这些技术。此外,文中还讨论了不同方法在性能上的优劣,为开发者提供了实用的参考。 ... [详细]
  • 本文详细探讨了 jQuery 中 `ajaxSubmit` 方法的使用技巧及其应用场景。首先,介绍了如何正确引入必要的脚本文件,如 `jquery.form.js` 和 `jquery-1.8.0.min.js`。接着,通过具体示例展示了如何利用 `ajaxSubmit` 方法实现表单的异步提交,包括数据的发送、接收和处理。此外,还讨论了该方法在不同场景下的应用,如文件上传、表单验证和动态更新页面内容等,提供了丰富的代码示例和最佳实践建议。 ... [详细]
  • 本文深入探讨了JavaScript中`this`关键字的多种使用方法和技巧。首先,分析了`this`作为全局变量时的行为;接着,讨论了其在对象方法调用中的表现;然后,介绍了`this`在构造函数中的作用;最后,详细解释了通过`apply`等方法改变`this`指向的机制。文章旨在帮助开发者更好地理解和应用`this`关键字,提高代码的灵活性和可维护性。 ... [详细]
  • 在 JavaScript 中,浮点数的除法运算常常会出现精度问题。本文介绍了一种方法,通过自定义函数来精确控制除法运算结果的小数位数,确保计算结果的准确性。该方法不仅适用于除法,还可以扩展到其他浮点数运算,有效避免了 JavaScript 在处理浮点数时常见的精度误差。 ... [详细]
  • 2.2 组件间父子通信机制详解
    2.2 组件间父子通信机制详解 ... [详细]
  • 微信小程序实现类似微博的无限回复功能,内置云开发数据库支持
    本文详细介绍了如何利用微信小程序实现类似于微博的无限回复功能,并充分利用了微信云开发的数据库支持。文中不仅提供了关键代码片段,还包含了完整的页面代码,方便开发者按需使用。此外,HTML页面中包含了一些示例图片,开发者可以根据个人喜好进行替换。文章还将展示详细的数据库结构设计,帮助读者更好地理解和实现这一功能。 ... [详细]
author-avatar
手机用户2502937497
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有