经典的案例

let arr = []
for(var i =0;i<=5;i++){
arr[i]= function fn(){
console.log(i)
}
}
arr[0]() //6

解析:我们的想法是arr[0]的函数应该是打印0的,而且每个元素的函数都能打印出自己的索引才对,可结果出乎意料。实际上为啥是6,我们先逐步分析。

1.js没有块级作用域

for(var i =0;i<=5;i++){
b=3
console.log(i)
}
{var a =1}
console.log('结果:',a,b) //结果: 1 3

也就是说,在大括号中声明的变量在大括号外部能拿到。这些变量是全局变量。

2.函数操作的变量值是函数调用时的而非函数声明时的

var a = 1
var fn = function(){
console.log('a:',a)
}
a=2
fn() //a:2

函数声明时变量a的值是1,声明后a的值变成了2,此时再调用fn函数,取得的a是2.

3.for循环的变量泄漏

let arr = []
for(var i =0;i<=5;i++){
arr[i]= function fn(){
console.log('i',i)
}
}
//实际上此时的arr是,[fn,fn,fn,fn,fn,fn]
console.log('i:',i) //i:6
arr[0]() //i 6
//实际上就是 console.log('i',i),而此时的i变成了6,无论是数组的第几个元素,最终打印的都是6

如果我希望每个元素都是打印它的索引,如何解决这个问题

方案1:闭包

返回一个函数,实际上就是我希望函数里打印的变量时当时循环的i的值,那我就把这个值作为参数传进去.所以,我用函数去返回一个函数

let arr = []
for(var i =0;i<=5;i++){
var fn = function(a){
return function(){
console.log('i',a) //打印的并不是全局变量i,而是实参'i'
}
}
arr[i]= fn(i) //调用的时候,i是当前循环的值
}
arr[0]() //i 0

我们常说闭包可以用来延长变量的使用寿命,实际上就是单独用一个函数作用域去保存外部变量值.

方案2:let和const

let和const声明的变量常被视为块级作用域,即虽然js无块级作用域的说法,但是let 和const的功能可以被视作块级作用域

let arr = []
for(let i =0;i<=5;i++){
arr[i]= function fn(){
console.log('i:',i)
}
}
arr[0]() //i 0

如下:

let arr = []
{let a = 1
arr[0] =function (){
console.log('a:',a)
}}
{let a =2
arr[1] = function(){
console.log('a::',a)
}}
arr[0]() //a: 1
arr[1]() //a:: 2

说明,let声明的变量,在一个大括号里是可以视作独立的存在的。类似块级作用域的效果,如果把let换成var,那就会提升为全局变量,最后被后面的赋值修改。

for循环中的变量泄漏的更多相关文章

  1. js for 循环中的 变量问题。

    今日处理项目中的一个循环,本来就是一个小小的for循环,后来发现该段程序出现了问题,仔细检查代码没有发现其中的错误.无奈只好叫来了老大帮忙.通过在模版中断点调试(该方式只能自己写debugger断点) ...

  2. 【SQL】小心在循环中声明变量——浅析SQL变量作用域

    本文适用:T-SQL(SQL Server) 先看这个语句: --跑3圈 BEGIN --每圈都定义一个表变量,并插入一行 DECLARE @t TABLE(Col INT PRIMARY KEY) ...

  3. 用闭包解决 js 循环中函数变量暂存问题

    需求:有一个数组,根据数组的值渲染对应的数字div,单击对应的div 在控制台打印对应的数字.如点击1,控制台打印1. 问题: 不管点击哪个值 打出来都是4 代码如下 <!DOCTYPE htm ...

  4. Python语言程序设计之一--for循环中累加变量是否要清零

    最近学到了Pyhton中循环这一章.之前也断断续续学过,但都只是到了函数这一章就停下来了,写过的代码虽然保存了下来,但是当时的思路和总结都没有记录下来,很可惜.这次我开通了博客,就是要把这些珍贵的学习 ...

  5. 16.1 foreach 循环中捕获变量的变化

    在 foreach 循环内的匿名函数(通常为Lambda表达式)中捕获循环 变量时要格外小心.代码清单16-1就展示了这样一个简单的示例,它看上去似乎会输出 x . y . z . string[] ...

  6. 关于在for循环中绑定事件打印变量i是最后一次。

    其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  7. 关于while read line 循环中变量作用域的问题

    前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据.于是用到了while read line 作为循环. 在制作文件计数器的时候发现了一个问题,在 ...

  8. 注意for循环中变量的作用域-乾颐堂

    1 2 for e in collections:     pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循 ...

  9. 注意for循环中变量的作用域

    for e in collections: pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循环之前已经有一个 ...

随机推荐

  1. 高德地图 JS API (jsp + miniui(子页面数据返回父页面并设值) + 单个点标记 + 点标记经纬度 + 回显 + 限制地图显示范围+搜索)

    -*-  父页面js function mapFocus(){ //console.log("-*-"); var longitude = mini.get("jd&qu ...

  2. 菜鸡的Java笔记 图书馆

    图书大厦        开发要求            现在要求模拟一个图书大厦图书管理的程序结构,可以在图书大厦实现某一类图书的上架操作,下架操作,以及关键字模糊查询的操作            注 ...

  3. 介绍一款docker管理工具——portainer

    介绍一款docker管理工具--portainer 目录 介绍一款docker管理工具--portainer 1.背景 1.1 管理docker方法上一般有两种 1.1.1 命令行形式 1.1.2 U ...

  4. GDI绘制Winform工作流组件、具有独立图层的增删处理、防PPT效果

    最近接了个小项目10K.用了2个下班时间写完,共花费了6-7个小时完成.如有同类需求的可以与本人联系,QQ:120772981 功能目标: 需要写一个仿PPT画泳道图的组件.之前写过工作流的组件,其实 ...

  5. Mybatis类型转换BUG

    案例:mybatis框架的使用中是否遇到过前台传入数据后mybatis后台并不执行sql的情况呢? 比如:前台传入一个状态var flag //空字符,0,1 然后你用int接收,到mybatis框架 ...

  6. 多线程Reactor模式

    目录 1.1 主服务器 2.1 IO请求handler+线程池 3.1 客户端 多线程Reactor模式旨在分配多个reactor每一个reactor独立拥有一个selector,在网络通信中大体设计 ...

  7. VSCode + PicGo + Github + jsDelivr 搭建稳定快速高效图床

    VSCode + PicGo + Github + jsDelivr 搭建稳定快速高效图床 目录 前言 准备 配置 验证 前言 所谓图床,就是将图片储存到第三方静态资源库中,其返回给你一个 URL 进 ...

  8. python-django 使用class重写视图和模板变量

    基于类的视图 c Django模板语法 两个模板引擎如何进行模板文件的查找 模板引擎都找不到的时候,就照模块里面的模板 一旦找到模板不会继续查找了 注意:img_addr是必须和视图里面的变量名字保持 ...

  9. python 调用系统软件

    直接使用os模块的popen打开 import sys import os a=os.popen('/Soft/samtools-1.2/samtools flags '+sys.argv[1] ,' ...

  10. linux 线程函数小结

    由于主线程已经开始跑了,次线程还在使用串口打印需要一点时间,因此打印的都是重复的. #include "pthread.h" #include "stdio.h" ...