闭包
一、闭包定义
函数嵌套函数,子函数访问父函数的变量,就产生了一个闭包环境
function fn1(){
var n=10; //n是在函数内声明的,局部变量,它在函数外面是访问不到的
function fn2(){ //fn2是在函数内声明的,局部函数,它在函数外面是访问不到的
n++;
console.log(n); //11
}
fn2();
}
//fn2(); 这里是不能够访问到fn2的函数
fn1(); //11
fn1(); //11
//console.log(n); //报错 那么如何让局部域的变量和函数,在全局被访问到?
二、生命周期与垃圾回收机制
生命周期
* 变量或者函数在相应的作用域里存在的时间
* 局部变量:不再使用了,就是生命周期的结束。局部变量是在函数内声明的,当函数执行完成以后,这个变量就不存在了
* 全局变量:声明完成以后,在整个页面中都可以用。当页面关闭的时候,它的生命周期就结束了 * 垃圾回收机制
* 变量存在内存当中的,变量在使用完以后,没有在其它的地方再使用,就会被清除,用来释放内存。垃圾回收机制会按照固定 的时间,周期性的执行
1. function fn1(){
var b=12;
}
fn1();
//console.log(b); //报错 变量b在函数fn1执行完成以后,发现在别的地方没有再使用,那它就会被垃圾回收机制所回收
//就是局部作用是基于垃圾回收机制的 2. function fn2(){
var n=10;
function fn3(){
n++;
console.log(n);
}
fn3();
}
fn2(); //11
fn2(); //11
//fn2函数在执行完成以后,变量n在其它的地方没有被使用,所以n在fn2执行完成以后会被垃圾回收机制 所回收。再去设fn2的时候,此时内存当中已经没有n这个变量了,只不过是重新声明了一个n三、闭包的作用
让函数内的局部变量与局部函数,在外面(不一定是全局变量,只是相对于该局部的)可以访问到
方法有两种
1、定义一个全局变量,放入到局部域里面,然后将需要的局部变量和函数赋值给它,然后再全局就能调用。
var innerFn=null; //全局变量,用来存储内部函数
function fn1(){
var n=10;
function fn2(){
n++;//n=n+1
console.log(n);
}
fn2(); //这里执行了函数之后得到的结果就是一个数
innerFn=fn2;
}
fn1(); //11
innerFn(); //12 把fn2整个函数赋给了innerFn,而它本身就是一个全局变量,有了值以后在其它的地方就可以访问到它了
innerFn(); //13 因为fn2变成了全局变量,因此它的变量没有被垃圾回收机制回收。因此不断累加 2、将局部变量以及函数从局部域调出到全局域,那么在外面就能访问到了。
function fn1(){
var n=10;
function fn2(){
n++;
console.log(n);
}
return fn2; //这里的意思是把fn2返回到了fn1的结果, 既是fn1()=function fn2(){};
}
console.log(fn1()); //fn1()=function fn2(){};
var newFn=fn1();
/* 相当于 var newFn=function fn2(){ 相当于将fn2从局部的函数调出到了全局。并且把函数说明变成函数表达式
n++;
console.log(n);
}*/
newFn(); //11
newFn(); //12四、闭包的应用
1.在循环中找到对应的值
window.onload=function(){
var lis=document.querySelectorAll('li');
//var i=0;
for(var i=0;i<lis.length;i++){
//利用作用域访问的关系。不让i访问到for
lis[i].onclick=(function(i){
//这里给的形参就说明在这个局部域里面有i,所以找值得时候,找到这里就停了,不用找到上面一层for的i, for的i永远是length
function fn2(){
console.log(i);
}
return fn2;
})(i); //相当于把fn2从里里面的域带了出现,但是i的值还是从里面开始查找起。
}
}
<ul>
<li>red</li>
<li>green</li>
<li>blue</li>
<li>yellow</li>
<li>pink</li>
</ul>