JavaScript 闭包的理解

在了解闭包之前,我们先来了解下局部变量全局变量

局部变量
即为定义在局部作用于下的变量,仅在这个作用域下被调用;


全局变量
即为定义在window下,在任何地方都可以调用。

那么他们有哪些优缺点呢?
局部变量用完会随着当前程序一同被销毁,不会占用内存,但是不可以重复使用。
全局变量可以重复使用,但是很容易造成变量污染。
看来局部变量和全局变量都有他的优缺点,
那么怎么样才能够变量重用,又可以保护变量不会被污染的一种机制呢?
答案当然是有的,这就是今天要介绍的内容 闭包

什么是闭包(closure)?

首先我们来看看分别在百度百科,菜鸟教程,W3Cschool和ECMAScript中对闭包的描述。

百度百科
闭包就是能够读取其他函数内部变量的函数。

菜鸟教程
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。 直观的说就是形成一个不销毁的栈环境。

W3Cschool
JavaScript 变量可以是局部变量或全局变量。
私有变量可以用到闭包。

ECMAScript
闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。

综上所述,闭包就是外层函数的内层函数可以使用外层函数的变量。
怎么去理解这句话呢?
我们都知道,一般函数在执行完后会出栈,但是闭包导致作用域链不被释放,所有内层函数即使在外层函数执行完成后仍然可以访问外层函数里的变量。

function test(){
	var a = 100;
	return function (){
		console.log(a);
	}
}
var result = test();
result();

如上代码所示,代码在预编译GO存在testresulttest 指向function test(){...}函数体,resultundefined,当函数test()执行时,testAO存在a,执行后a的值100,在GO中的result赋值为function(){console.log(a)},此时test出栈,但是因为test内变量aresult所引用,所以testAO无法被释放,result可以访问到testAO内的值,其中a为受保护的变量。

闭包在开发中有什么作用?

在开发中我们会经常的使用动态添加点击事件,我们按照思维通常会写成下面这样

function test(){
	var liList = document.getElementsByTagName("li");
	for(var i = 0; i < liList.length;i++){
		liList[i].onclick = function(){
			console.log(i);
		}
	}
}
test()

但是因为我们在外层函数里使用了内层函数,并且使用了外层函数的变量i,形成了闭包
内层函数每一次循环都可以调用外层函数的值并且每次自增1,而点击事件返回的函数体,此时并没有去执行;
当我们触发点击事件时,此时外层函数的iliList.length,则每一次点击的iliList.length,与我们预想的结果不同。

怎么去解决闭包所带来的问题?

闭包无非就是返回的函数内受保护的变量没有被放入返回的函数体内,只是返回了函数的内容,那么我们只需要让他返回具体的值。

function test(){
	var liList = document.getElementsByTagName("li");
	for(var i = 0; i < liList.length;i++){
		(function(j){
			liList[j].onclick = function(){
				console.log(j);
			}
		}(i))
	}
}
test()

如上代码所示,i是变化的,但是只能返回i,不能返回i的值;我们定义一个匿名的函数,讲i的值传入这个匿名函数,则每次返回的为console.log(1);console.log(2)......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值