function a(){
function b(){
var bbb = 234;
document.write(aaa);
}
var aaa = 124;
return b;
}
var glob = 100;
var demo = a();
demo(); // 124
a() 执行完了,要销毁a的AO,
但是在销毁AO之前,把b保存到外面去了,把a()执行的结果放到demo里面去了,
在demo执行之前,a的AO已经被销毁了,但是b还有a的AO
function a(){
var num = 100;
function b(){
num ++;
console.log(num);
}
return b;
}
var demo = a();
demo(); // 101 相当于执行b,num是a的AO
demo(); // 102 再次执行,还是在a的AO中找
函数里面的函数被保存到外面,一定会形成闭包。
闭包会导致原有的作用域链不释放,造成内存泄漏。
闭包的作用
实现公有变量
累加器
function add(){
var count = 0;
function demo(){
count ++;
console.log(count);
}
return demo;
}
var counter = add();
counter();
可以做缓存(存储结构)
function test(){
var num = 100;
function a(){
num++;
console.log(num);
}
function b(){
num--;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0](); // 101
myArr[1](); // 100
function test(){
var food = 'apple';
var obj = {
eatFood:function(){
if(food != ""){
console.log("i am eating "+ food);
food = "";
} else{
console.log("empty");
}
},
pushFood:function(myFood){
food = myFood;
}
}
return obj;
}
var person = test();
person.eatFood(); // i am eating apple
person.eatFood(); // empty
person.pushFood("banana");
person.eatFood(); // i am eating banana
eatFood这个函数被保存出来了形成了闭包,要保存原来test的劳动成果,pushFood这个函数同样如此,他们两个都保存test的劳动成果,保存的是不是同一个呢?
大家保存的都是同一个劳动成果,大家修改的都是同一个东西。
多个函数同时和一个函数形成闭包,他们之间的变量相当于可以公用。
可以实现封装,属性私有化
function Person(name,wife){
var prepareWife = "xiaozhang"
this.name = name;
this.wife= wife;
this.divorce = function(){
this.wife = prepareWife;
}
this.changePrepareWife = function(target){
prepareWife = target;
}
this.sayPrepareWife = function(){
console.log(prepareWife);
}
}
var person = new Person("minmin","xiaoyang");
// person.prepareWife = undefined
模块化开发,防止污染全局变量
function test() {
var arr = [];
for(var i = 0;i < 10;i++){
arr[i] = function() { // arr[i]=函数,函数是什么不用考虑
console.log(i)
} // 函数
}
return arr;
}
var myArr = test();
for(var j = 0;j < 10;j++){
myArr[j](); // 在这执行的时候才去找函数里面的i是什么,此时的i变成10了
}
// 打印10个10
function test() {
var arr = [];
for(var i = 0;i < 10;i++){
(function (j){ // j 形参
arr[j]=function(){
document.write(j+"");
}
})(i); // i 实参
}
return arr;
}
var myArr = test();
for(var j = 0;j < 10;j++){
myArr[j](); // 在这执行的时候才去找函数里面的i是什么,此时的i变成10了
}
立即执行函数放到for循环中,有10个立即执行函数
// j=0
(function (j){ //
arr[j]=function(){
document.write(j+"");// 找的是立即执行函数里面的j
}
})(i); // i=0
// j=1
(function (j){ //
arr[j]=function(){
document.write(j+"");
}
})(i); // i=1
案例
输出小li的索引
<style>
*{
margin:0;
padding: 0;
}
ul{
list-style: none;
}
li:nth-of-type(2n){
background-color: antiquewhite;
}
li:nth-of-type(2n+1){
background-color:azure;
}
</style>
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
<script type="text/javascript">
function test(){
var liCollection = document.getElementsByTagName('li');
for (var i = 0; i < liCollection.length; i++) {
liCollection[i].onclick = function () {
console.log(i);
}
}
}
test();
</script>
function test(){
var liCollection = document.getElementsByTagName('li');
for (var i = 0; i < liCollection.length; i++) {
(function(j){
liCollection[j].onclick = function () {
console.log(j);
}})(i);
}
}
test();