JS闭包理解
一、什么是闭包?
闭包就是能够读取其他函数内部变量的函数。是一种解决问题的办法、一种特殊结构 ,使得重复使用变量又不让变量被污染的机制。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的内存回收机制)
但是!如闭包这样的,一个函数(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夯实基础系列之闭包