欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS闭包理解

程序员文章站 2022-05-07 18:56:27
...

一、什么是闭包?

闭包就是能够读取其他函数内部变量的函数。是一种解决问题的办法、一种特殊结构 ,使得重复使用变量又不让变量被污染的机制。JS中只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

二、闭包直观表现

1、函数内部可以访问函数外部的全局变量。

var a = 1;//全局变量
        function f1(){ 
              b = 2 ;            //全局变量。在函数内部定义变量时,要加上var,否则该变量就是全局变量了
           document.write(a);
           
        }
        f1();

2、但函数外部不能访问函数内部的局部变量,

function f2(){
           var a = 1 ;        //局部变量
       }
         document.write(a);

3、但是,若我们想得到函数内部的局部变量,这就引入了闭包的概念啦。

在代码中注释让人看得更加清楚:
  var a = 1;                                //全局变量。一般来说,函数内部可以访问函数外部的全局变量。
function outer(){                           //外部函数
		var num = 100;                      //局部变量。  函数外部不能访问函数内部的局部变量,                   
			function enter(){              //内部函数
			   var b = 100                 //也是局部变量。
			     a = 1 ;                   //!!**全局变量**!!在函数内部定义变量时,要加上var,否则该变量就是全局变量了
				var s = "hello world";
				document.write(num);
			}
			return enter;                 //此句的作用是将内部函数变量的值返回
		}
		var a = 100;
		var getEnter = outer();           // 由于作用域链的配置机制,使得闭包只能取得包含函数中任何变量的最后一个值。
                                      		即说明了闭包中所保存的是整个变量对象,而不是某一个特殊的变量。
		getEnter();//100

三、从作用域链分析

JS闭包理解
注释:闭包会将将变量的值始终保存在内存中(会消耗很大内存,所以不能滥用闭包造成网页的性能问题,故不能滥用闭包)
通常情况中,当函数执行完毕之后,函数内部的局部活动对象就会被销毁,内存中仅保存全局作用域,(即js的内存回收机制)
但是!如闭包这样的,一个函数(a)内又嵌套了另一个函数(b),该函数(b)是有可能在外部被调用到的.并且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题。这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(比如被删除了,或者没有了指针),才会销毁这个闭包。

四、拓展应用

<body>
<ul>
		<li>1</li>
		<li>2</li>
		<li>3</li>
		<li>4</li>
		<li>5</li>
		<li>6</li>
		<li>7</li>
		<li>8</li>
	</ul>
	<script>
		function addClick(){
			var liList = document.getElementsByTagName("li");
			for(var l = 0; l < liList.length; l ++){
				(function(j){
					liList[j].onclick = function(){
						console.log(liList[j].innerHTML);
					}
				}(l));
				
			}
		}
		addClick();
		</script>
		</body>

在function addClick()这个函数中,我们没有直接将闭包赋值给数组,而是定义了一个匿名函数 function(),并将立即执行该匿名函数的结果赋值给数组。
对于立即执行的匿名函数来说,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放。所以这里的匿名函数有一个参数J,也就是最终的函数要返回的值。
在调用每个匿名函数时,我们传入了变量i。由于函数是按值传递的,所以会将变量i的当前值赋值给参数j,而这个匿名函数内部,又创建并返回了一个返回j的闭包。这样一来,数组中的每个函数都有自己j的一个副本,因此就可以返回各自不同的数值了。

相关标签: JS闭包理解