什么是闭包
要理解闭包就要去理解变量的作用域,在JS中存在两种变量的作用域,一种是全局变量,一种是局部变量。两种变量的区别就是函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

那什么是闭包呢?闭包是指有权访问另外一个函数作用域中的局部变量的函数。声明在一个函数中的函数,叫做闭包函数。而且内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

闭包的特点
1、让外部访问函数内部变量成为可能

2、局部变量会常驻在内存中

3、可以避免使用全局变量,防止全局变量污染

4、会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,并且互不干扰。闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。大概意思就是说当外部函数运行结束甚至销毁时,局部的变量key=value,尽管key被垃圾回收机制给回收了,但是value仍不会被回收,会变成一个自由变量留下引用的指针。

这一天也是看了不少的例子,还是有一些没理解清楚的,回来理解一下再过来更新,还是先把我理解了的分享出来,记录讲解一下我的理解。

例子1

var age = 10;
function foo(){
console.log(age);//-----------------1
var name = "hunt_bo";
return function(){
console.log(name);
}
}
console.log(name);//---------------2
var bar = foo();
bar();


这个应该说是最简单的一个闭包的例子了,那就用他来介绍一下闭包的基本概念,首先呢是函数内部肯定是可以访问到全局变量的值的,所以在foo()函数中去打印age肯定是可以打印出来的,就像代码中的标记1,但是呢在标记2处打印的函数内部的变量name是打印不出来的。

但是当我们用到闭包的时候,在foo函数内部返回一个函数,在返回的函数中去用到局部变量name,最后呢在外部调用,这时候的bar仍然在函数外部,但是完全可以拿到局部变量的name值。这就是闭包的定义吧,同样呢也是闭包的第一个特点。

例子2

function addCount(){
var count = 0;
return function(){
count += 1;
console.log(count);
}
}
var fun1 = addCount();
var fun2 = addCount();
fun1();//1
fun1();//2
fun1();//3
fun2();//1
fun2();//2


这个例子呢,跟第一个也算是差不多的,就是在返回函数中做了一个递增并打印的操作,把addCount的返回函数给到fun1和fun2,当我向上面代码一样调用的时候呢,就会发现替他打印的不是12345,而是12312,那这是什么原因呢,这就回到了上边介绍的那句话:每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。所以说虽然fun1和fun2都是addCount(),但是呢都创建了新地址,都是自己的,互不干扰。

例子3

var i = 0;
function outerFn(){
function innerFn(){
i++;
console.log(i);
}
return innerFn
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();//1
inner2();//1
inner1();//2
inner1();//3
inner2();//2
inner2();//3

例子4

function fn(){
var a = 3;
return function(){
return ++a;
}
}
console.log(fn()());//4
console.log(fn()());//4
console.log(fn()());//4
var newFn = fn();
console.log(newFn());//4
console.log(newFn());//5
console.log(newFn());//6

例子5

(function() {
var m = 0;
function getM(){
return m;
}
function seta(val){
m = val;
}
window.g = getM;
window.f = seta;
})();
f(100);
console.log(g());//100

例子6

var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
console.log(i);
};
})(i);
}

说句题外话就是在现实应用中我是不会这样用,let它不香么,这么复杂。

再来最后一个例子吧,就是我在面试中面试官给我的那道题: