理解JavaScript的闭包

闭包:函数和对其周围状态(词法环境)的引用捆绑在一起构成闭包,闭包可以让你从内部函数访问外部函数作用域。

看了这位大佬的文章了解了很多,指路====》转载自闭包

首先一道题:

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

打印出来是5 5 5 5 5 5,没有问题。

  • 而代码实际运行情况呢?怎么描述? 应该是5 - > 5, 5, 5, 5, 5
  • 为什么?—— 循环执行过程中,几乎同时设置了5个定时器,而且都是在一秒后触发,而且循环完的输出几乎是立即执行的。
如果期望输出为:5 -> 0,1,2,3,4,怎么解决?
方法一:闭包
for(var i=0;i<5;i++){
	(function (j){
		setTimeout(function(){
		console.log(new Date, j)
	}, 1000)
	})(i)
}
console.log(new Date, i)

在这里插入图片描述

方法二:setTimeOut第三个参数
for(var i=0;i<5;i++){
	setTimeout(function(j){
		console.log(new Date, j)
	}, 1000, i)
}
console.log(new Date, i)

在这里插入图片描述

方法三:函数传参(利用js基本类型的参数传参是按值传参)
var output = function (i) {
	setTimeout(function(){
		console.log(new Date, i)
	}, 1000)
}
		
for(var i=0;i<5;i++){
	output(i)
}

console.log(new Date, i)

在这里插入图片描述

方法四: es6 let(会报错)

可以倒是可以但是会报错。。。因为最后的那个i的作用域并没有i定义

for (let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

在这里插入图片描述

如果期望输出改为0 -> 1 -> 2 -> 3 -> 4 -> 5,怎么处理?

可以在之前的基础上进行修改,如下:

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

在这里插入图片描述
在这里插入图片描述
这种思路是可以的,但是全部都是异步操作,不是很好。

可以使用Promise:
		const task = []
		for (var i=0;i<5;i++) {
			((j) => {
				task.push(new Promise((resolve) => {
					setTimeout(() => {
						console.log(new Date,j)
						resolve()
					}, 1000 * j)
				}))
			})(i)
		}

		Promise.all(task).then(() => {
			setTimeout(() => {  // 这个promise.all里面一定要个setTimeOut,否则最后4,5会一起出来,就不能实现打印4隔一秒再打印5
				console.log(new Date, i)
			}, 1000)
		})

在这里插入图片描述

闭包的实用:

闭包允许将函数与其所操作的某些数据(环境)关联起来。类似于面向对象编程。

可以使用闭包模拟私有方法:

在这里插入图片描述

闭包的缺点:
  1. 闭包使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用。否则会造成内存泄漏,造成网页的性能问题。(解决:在退出函数之前,将不使用的局部变量全部删除)
  2. 闭包会在父函数外部,改变父函数内部变量的值,如果把父函数当成对象使用,会把闭包当成他的公有方法,把内部变量当成私有变量。
闭包的优点:
  1. 闭包加强了封装性,保护变量安全
  2. 私有成员的产生
  3. 延长作用域链
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值