闭包认知
·
3 min read
最近在梳理JS基础,觉得
闭包
这个知识点并不清晰,研究了会儿,所谓踏雪有痕,这里MARK下。
什么是闭包
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起
构成 闭 包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
摘自MDN
注意
- 函数作用域,不是块作用域
- 闭包是有状态的函数
先上几个例子,看看谁是闭包
例子1
function init() {
var name = 'Mozilla'; // name 是一个被 init 创建的局部变量
function displayName() {
// displayName() 是内部函数
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
init();
例子2
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
TIP
注意,Chrome调试状态下是可以看出来谁是闭包
的。有助于去理解。
通过这几个例子实际上可以这么去说
闭包即是可以访问其他函数作用域内变量的函数对象
,同时你可以说闭包是有状态的函数
。
闭包的运用
知道谁是闭包,那么就是闭包可以干嘛。
- 封装私有变量
- 模块
- 用在块作用域上
- 监听器
这几种用法,我们只是有意无意的在使用,可能只是不知道而已。
闭包是一种技术,不限语言
如上,闭包Closure是一种技术手段,所以与语言无关,那么比如java有闭包吗。有的。
Java中的闭包
比如最常见的lambda中,我们传入传入外部函数变量,从而形成闭包。
int factor = 3;
numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * factor)
.collect(toList());
为什么说这是个闭包,注意factor是函数外部的函数词法坏境
概念困惑 - lambda,匿名函数,闭包
- lambda即匿名函数,两个叫法而已
- 闭包跟匿名函数并不同,如上例子中,如果factor去掉,其实就不是闭包了
上题
闭包后,来看几道复杂点的题。
题1
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
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及其
写在最后
编程界崇尚以简洁优雅为美,很多时候如果你觉得一个概念很复杂,那么很可能是你理解错了
,这句话深表认同。带着这样的认识去看待诸如闭包这样的概念,我想应该会更简单些。