JavaScript 函数 | 闭包和它的用途以及看了头皮发麻的链式调用

1. 闭包

闭包:被函数包裹的变量 = >在内部函数中可以访问外部函数声明的变量

2. 闭包的用途

2.1 结果缓存

闭包不会释放外部变量的引用,能将外部变量值缓存在内存中。如果内存中有,则直接返回;如果没有,则调用函数并进行缓存,保存结果

2.2 封装

2.2.1 输出li的索引值

业务场景:ul有若干个li,每次单击li,输出li的索引值

let lis = document.getElementsByTagName('ul')[0].children;
for( let i = 0;i<lis.length;i++){
	// 创建一个匿名立即执行函数
	(function(index){
		// 对外部变量lis的引用,创建闭包
		lis[index].onclick = function(){
			console.log(index);
			}
	})(i);
}

2.2.2 定时器

业务场景:定时器setTimeout()函数与for()循环搭配使用

let arr = ['1','2','3','4'];
for( let i = 0;i<arr.length;i++){
		// 创建一个匿名立即执行函数
		(function(time){
			setTimeout(function(){
			// 对外部变量arr的引用,创建闭包
			console.log(arr[time])
			},time*1000);
	})(i);
}

2.2.3 作用域链问题

业务场景:闭包与this属性

var name = "outer";
var obj = {
	name:"inner";
	method:function(){
		// 保存obj对象中的this
		var _this = this;		
		return function(){
			return _this.name;
			}
		}
};
// 调用method()方法,然后在匿名函数的返回值中再去调用_this.name
console.log(obj.method()());// inner

2.2.4 多个相同函数名问题

第一眼看到这道题的同学,头皮发麻的请点赞!

// 第一个foo()函数是具名函数,返回一个具体的对象
function foo(a,b){
	console.log(b);
	return {
		// 第二个foo()函数是第一个foo()函数返回对象的一个属性,指向一个匿名函数
		foo:function(c){
		// 第三个foo()函数是被返回的函数,会沿着原型链向上查找;
		//最终指向第一个foo()函数,即第三个foo()函数和第一个foo()函数实际上是指向同一个函数
			return foo(c,a);
		}
	}
}
var x = foo(0);x.foo(1);x.foo(2);x.foo(3);// undefined,0,0,0
var y = foo(0).foo(1).foo(2).foo(3);// undefinde,0,1,2
var z = foo(0).foo(1);z.foo(2);z.foo(3);// undefined,0,1,1

解析:

var x = foo(0);x.foo(1);x.foo(2);x.foo(3);
1. 由于变量x在执行foo(0)时,没有传入b值,所以是console.log(b)=>输出:undefined
2. 由于第三层foo()函数和第一层foo()函数是同一个函数,且foo()函数闭包了外层的a值,所以实际调用是第一层的foo(1,0)=>输出:0
3. x.foo(2)和x.foo(3)的原理同上,输出0
=================================================
var y = foo(0).foo(1).foo(2).foo(3);
4. 由于变量x在执行foo(0)时,没有传入b值,所以是console.log(b)=>输出:undefined
5. 链式调用foo(1),由于闭包存在(即对a的引用,此时a=1),实际调用为foo(1,0)=>输出:0 
6.执行foo(2),此时a的值等于2,返回foo(2,1),,又由于foo()函数指向第一个foo()函数=>输出:1 
7.执行foo(3),此时a的值等于3,返回foo(3,2),,又由于foo()函数指向第一个foo()函数=>输出:2
==================================================
var z = foo(0).foo(1);z.foo(2);z.foo(3);
8. foo(0).foo(1)的调用过程和前面的一样=>输出:undefined,0
9. 由于闭包了变量a的值为1,所以当调用z.foo(2)时,实际上是返回foo(2,1)=>输出:1
10. 由于闭包了变量a的值为1,所以当调用z.foo(3)时,实际上是返回foo(3,1)=>输出:1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是希望

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

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

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

打赏作者

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

抵扣说明:

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

余额充值