闭包

1----------------

var x = 100;
function test(){
    console.log(x);
}
//对于这个样式,x与test存在着链条关系,test可以访问x,即使换了位置这种关系是不会发生变化的
function test1(){
    var x = 100;
    return function test(){
        console.log(x);
    }
}
//对于这种形式,test还是可以访问x,只是x变成了局部变量,那我们可以把test返回出来,当执行test1的时候
//返回的是test函数,test1执行完了,变量x就被清除了吗,不是的,因为test函数还在使用变量x
var t = test1();
t();//结果是 100
//这样执行test返回的函数用变量t来保存,并执行,便可以访问局部变量x的值,
//这样情况就形成了闭包,本质就是把函数内部与外部连接起来的桥梁,也可以理解为闭包是在函数内部定义一个函数,也可以说闭包是可以有权访问读取其他函数内部变量的函数
//闭包的用途:可以访问其他函数内部变量,其次是让变量常驻内存,不会因为父级函数执行完而被清理掉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

二------------

for(var i=0;i<5;i++){
    +function(){
        for(var i=0;i<5;i++){
            console.log(i);
        }
    }()
}
//+function(){}()函数的自运行,前边的+可以是任何特殊字符,其速度比(function(){})()快5至6倍
//这种形式,两次定义的变量i已经不在一个作用域内了,互不影响,故console会执行25次,对于外部for循环,会生成5个上下文环境,每个上下文环境内部会执行5次
for(var i=0;i<5;i++){
    for(var i=0;i<5;i++){console.log(i);}
}
//这两个for循环输出结果是0,1,2,3,4,for循环中的{}不会产生作用域,声明的变量i是全局变量,第二次声明会把第一次覆盖掉
//第二个for循环执行完,那么i已经是5了。故第一个for循环只会执行开始的一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14

三---------------------

function test(){
    var x = 100;
    return function(){
        console.log(++x);
    }
}
test()();// 100
test()();// 100
test()();// 100
test()();// 100
//返回函数的自运行,每次运行都会生成一个上下文环境,执行完之后便清除,每一次都会对变量x自加1
var t2 = test();
t2();// 101
t2();// 102
t2();// 103
t2();// 104
//返回函数赋值给一个变量t2,那么t2便是个函数了,只会生成一个上下文环境var t2 = test();
//那么后边执行t2的时候,都会对变量x进行更改,执行一次加一次,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

四 -------------

<button>0</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
var btn = document.getElementsByTagName("button");
for(var i=0;i<5;i++){
    btn[i].onclick = (function(num){
        return function(){
            console.log(num);
        }
    })(i)
}
//循环为按钮添加点击事件,想要使得在每个点击事件里面得到相应的顺序值,比如,第一个按钮得到的应该是0,第五个得到的是4,
//这个时候就要使用到闭包了,函数的自执行,每个点击事件都有了一个返回函数,但是没有执行,所以变量不会消失,因为还有函数需要引用那个变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15