闭包认知

最近在梳理JS基础,觉得闭包这个知识点并不清晰,研究了会儿,所谓踏雪有痕,这里MARK下。

什么是闭包

函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成 闭 包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。

摘自MDN

注意

  1. 函数作用域,不是块作用域
  2. 闭包是有状态的函数

先上几个例子,看看谁是闭包

例子1

1
2
3
4
5
6
7
8
9
function init() {
var name = 'Mozilla'; // name 是一个被 init 创建的局部变量
function displayName() {
// displayName() 是内部函数
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
init();

例子2

1
2
3
4
5
6
7
8
9
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();

TIP

注意,Chrome调试状态下是可以看出来谁是闭包的。有助于去理解。

通过这几个例子实际上可以这么去说

闭包即是可以访问其他函数作用域内变量的函数对象,同时你可以说闭包是有状态的函数

闭包的运用

知道谁是闭包,那么就是闭包可以干嘛。

  1. 封装私有变量
  2. 模块
  3. 用在块作用域上
  4. 监听器

这几种用法,我们只是有意无意的在使用,可能只是不知道而已。

闭包是一种技术,不限语言

如上,闭包Closure是一种技术手段,所以与语言无关,那么比如java有闭包吗。有的。

Java中的闭包

比如最常见的lambda中,我们传入传入外部函数变量,从而形成闭包。

1
2
3
4
5
6
int factor = 3;

numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * factor)
.collect(toList());

为什么说这是个闭包,注意factor是函数外部的函数词法坏境

概念困惑 - lambda,匿名函数,闭包

  1. lambda即匿名函数,两个叫法而已
  2. 闭包跟匿名函数并不同,如上例子中,如果factor去掉,其实就不是闭包了

上题

闭包后,来看几道复杂点的题。

题1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function fun(n, o) { 
console.log(o);
return {
fun: function(m) { // ③
debugger;
return fun(m, n); // ④
}
};
}


// 第一个例子
var a = fun(0); // 返回undefined
a.fun(1); // 返回 0
a.fun(2); // 返回 0
a.fun(3); // 返回 0

// 第二个例子
var b = fun(0)
.fun(1)
.fun(2)
.fun(3); // undefined,0,1,2

// 第三个例子
var c = fun(0).fun(1);
c.fun(2);
c.fun(3); // undefined,0,1,1

题2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var myObject = {
foo: 'bar',
func: function () {
var self = this;
console.log('outer func: this.foo = ' + this.foo); // bar
console.log('outer func: self.foo = ' + self.foo); // bar
(function () {
console.log('inner func: this.foo = ' + this.foo); // unfefined
console.log('inner func: self.foo = ' + self.foo); // bar
})();
},
};

myObject.func();

  • 这道题理论上多个考察点就是this指向问题,记得以前看书时,有句话讲的很棒,this永远指向调用它的对象。比如这里就是myObject。
  • func及其

写在最后

编程界崇尚以简洁优雅为美,很多时候如果你觉得一个概念很复杂,那么很可能是你理解错了,这句话深表认同。带着这样的认识去看待诸如闭包这样的概念,我想应该会更简单些。

参考文档