函数A的返回值为函数B,在函数A外面可以通过函数B来访问函数A里的局部变量。
变量污染
变量污染就是全局变量滥用,造成报错,覆盖等问题;简单讲就是使用了相同的标识符声明了全局变量,var关键字声明相同的变量名会覆盖,let、const重复声明相同的变量名会直接报错;
- var 可以声明提升 可以重复声明 定义的变量是全局变量
- const 、let可以声明块级作用域
- const声明时必须赋值
闭包函数
1 | function A(){ |
在A函数中定义一个B函数,通过B函数调用A的局部变量i.
所以闭包就是 函数A的返回值为函数B,在函数A外面可以通过函数B来访问函数A里的局部变量i
闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。
因为如果是全局变量,容易被改,如果是局部变量,别人又访问不到。
1 | function xxx(){ |
闭包造成内存泄露?
内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。
闭包里面的变量明明就是我们需要的变量(lives),所以不是内存泄露
为何有人说是?
因为 IE。IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。
立即执行函数
声明一个匿名函数,立即执行它,就是立即执行函数
1 | !function (){ |
感叹号可以换成 + - ~ 等符号,也可以换成括号。
那为什么要有这么个东西(好麻烦)
只有一个作用:创建一个独立的作用域。
这个作用域里面的变量,外面访问不到(即避免「变量污染」)。
这个作用不就恰恰是闭包所需要的吗!!!
所以之前的函数可以写成
1 | !function xxx(){ |
举例
1 | var liList = ul.getElementsByTagName('li') |
因为在点击之前i早变成了6,每个监听的元素都为6。
那么怎么解决这个问题呢?用立即执行函数给每个 li 创造一个独立作用域即可
1 | var liList = ul.getElementsByTagName('li') |
在立即执行函数执行的时候,i 的值被赋值给 ii,此后 ii 的值一直不变。
i 的值从 0 变化到 5,对应 6 个立即执行函数,这 6 个立即执行函数里面的 ii 「分别」是 0、1、2、3、4、5。