JavaScript函数中的闭包
闭包是JavaScript中的一大重点,也是难点(敲黑板),
闭包简单的来说:定义在函数内部的函数。
内部函数作为返回值。
闭包是由函数以及创建该函数的词法环境组合而成,这个环境包含了这个闭包创建时所能访问的所有局部变量,所以是能够读取其他函数内部变量的函数。
特点:能够读取函数内部的变量,变量始终保存在内存中。
接下来从上面三句话理解闭包:
1.闭包是一个“函数”,是定义在函数内部的一个函数,并作为返回值输出,示例中fn
即为闭包。
1 | function wrapFn(){ |
2.闭包是由函数以及创建该函数的词法环境组合而成
1 | function makeAdd(x){ |
这里我们定义了makeAdder(x)
函数,它接受一个参数x
,并返回一个新的函数。返回的函数接受一个参数y
,并返回x+y
的值。
从本质上讲,makeAdder
是一个函数工厂 — 他创建了将指定的值和它的参数相加求和的函数。在上面的示例中,我们使用函数工厂创建了两个新函数 — 一个将其参数和6求和,另一个和26求和。
fn1
和fn2
都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。在fn1
的环境中,x
为5。而在fn2
中,x
则为10。
注意:返回函数不要引用任何循环变量或者后续会发生改变的变量
1 | function count(){ |
上面示例中,每次循环都追加一个函数到arr数组中,并返回数组,可结果并不是我们认为的0, 1, 4
。
结果都是9
,原因在于返回的函数引用了循环变量i
,我们输出fn
的其中一个项可以看到和push
方法内部的函数一样,当f1保存count()
返回的函数时,函数并没有执行,而是在f1()
函数调用时
执行i * i
的计算,而此时for循环完成i
的值为3。