js笔记(二)闭包原理,作用及危害

js笔记(二)闭包原理,作用及危害

  • 什么是闭包
    • 闭包无处不在
    • 一个例子
    • 闭包的危害

什么是闭包

想必用过js的朋友都知道,js的函数作用域,提到函数作用域,就不得不提js的闭包了,那到底什么是闭包呢?既然要在解释一下,去百度复制粘贴就没意思了,我就通俗的解释一下。说白了,就是垃圾回收机制没有及时回收的“垃圾”,还是上代码:

function fun () {
	var a = 1;
	function  fn() {
	  console.log(a) // 1
	}
}
fun ()

看了上面这段代码,有些人会说这和闭包有什么关系呢?的确一开始我对闭包的概念没那么了解的时候也有同样的看法,但是随着对闭包理解的深入就明白了,其实在函数fn手里拿着拿着变量a在fn没执行之前a是不会被回收机制回收掉的,这就是闭包。

闭包无处不在

说起闭包好像高大上的样子,其实在我们写代码的过程中,闭包几乎是无处不在的,上代码:

<html>
<head>
...
head>
<body>
<button>你点我呀button>
<script>
	var oBtn = document.getElementsByTagName('button')[0]
	function  bindClick () {
		var a = 0
		oBtn.onclick = function () {
			alert(a++)
		}
	}
	bindClick()
script>
body>
html>

这时候,每点一下按钮都会弹出a的值,这个a为什么会一直都在呢? 就是因为js中的垃圾回收机制,知道这个a还有要用到的时候,所以并没有将其回收。如果把代码改成:

<html>
<head>
...
head>
<body>
<button>你点我呀button>
<script>
	var oBtn = document.getElementsByTagName('button')[0]
	function  bindClick () {
		var a = 0
		alert(a)
	}
	bindClick()
script>
body>
html>

那么当bindClick()执行完之后a就会被回收掉。

一个例子

这里举一个很经典的例子:

<html>
<head>
...
head>
<body>
<button>按钮1button>
<button>按钮2button>
<button>按钮3button>
<script>
	var oBtn = document.getElementsByTagName('button')
	function  fun () {
		for (var i = 0; i < oBtn.length; i++) {
			oBtn[i].onclick = function () {
				console.log(i)
			}
		}
	}
	fun()
script>
body>
html>

上面这段代码中当点击每个按钮之后控制台会输出什么呢?答案是:无论点击哪个按钮输出的都是3,这是为什么呢?这就是闭包很要命的一个特点,也可以说是js很要命的一点,for循环的时候每一次循环 i 都会加1但是,这时候 i 的值就会把上一次的覆盖掉,当循环完之后,console.log(i)的 i 就会向for循环的var i 要值而这时候的值是3所以无论点击哪个按钮,所打印出来的值都是3。说起来这好像不是闭包的错,好像的确不是,但是在没有块级作用域的情况下倒是可以通过闭包解决这个问题:

var oBtn = document.getElementsByTagName('button')
	function  fun () {
		for (var i = 0; i < oBtn.length; i++) {
			(function (i) {
				oBtn[i].onclick = function () {
					console.log(i)
				}	
			})(i)
		}
	}
	fun()

代码经过这样的改动后,当即按钮1就会输出0按钮2输出1…这又是为什么呢?说起来还是js没有块级作用域惹得祸,改动之后每次循环绑定点击事件的时候,都会创建一个全新的函数作用域,所以每一次都会声明一个独立的 i 在自执行函数执行时通过参数传递进去。
当然如果是es6的话有更容易的解决方法

var oBtn = document.getElementsByTagName('button')
   function  fun () {
   	for (let i = 0; i < oBtn.length; i++) {
   		oBtn[i].onclick = function () {
   				console.log(i)
   		}
   	}	
   }
   fun()

嘻嘻是不是很简单呢,不过这不是今天要说的话题。

闭包的危害

说起危害呀,最大的就是容易造成内存泄漏,不会受的变量越多,对系统造成的压力也就越大,自然就影响性能咯。好今天就这样,打好收工。

你可能感兴趣的:(技术,JavaScript,js)