A.2 处理闭包之间的交互
当存在多个内部函数时,很可能会出现意料之外的闭包。假设我们又定义了一个递增函数,这个函数中的增量为2:
代码清单A-9
- function outerFn() {
- var outerVar = 0;
- function innerFn1() {
- outerVar++;
- console.log('(1) outerVar = ' + outerVar);
- }
- function innerFn2() {
- outerVar += 2;
- console.log('(2) outerVar = ' + outerVar);
- }
- return {'fn1': innerFn1, 'fn2': innerFn2};
- }
- var fnRef = outerFn();
- fnRef.fn1();
- fnRef.fn2();
- fnRef.fn1();
- var fnRef2 = outerFn();
- fnRef2.fn1();
- fnRef2.fn2();
- fnRef2.fn1();
这里,我们通过对象返回两个内部函数的引用(这也示范了内部函数的引用逃脱父函数的另一种方式)。可以通过返回的引用调用任何一个内部函数:
(1) outerVar = 1
(2) outerVar = 3
(1) outerVar = 4
(1) outerVar = 1
(2) outerVar = 3
(1) outerVar = 4
这两个内部函数引用了同一个局部变量,因此它们共享同一个封闭环境。当innerFn1()
为outerVar
递增1时,就为调用innerFn2()
设置了outerVar
的新的起点值,反之亦然。同样,我们也看到对outerFn()
的后续调用还会创建这些闭包的新实例,同时也会创建相应的新封闭环境。面向对象编程的爱好者们会注意到,这在本质上是创建了一个新对象,自由变量就是这个对象的实例变量,而闭包就是这个对象的实例方法。而且,这些变量也是私有的,因为不能在封装它们的作用域外部直接引用这些变量,从而确保了面向对象的数据专有特性。