闭包 vs 对象

什么是闭包(closure)?它与对象(object)有何异同?

特殊变量: 自由变量

一般情况下,一个函数中的变量有参数局部变量两种。参数是一种已经绑定值的变量,
也叫做bound variable,它是外部环境给予的。局部变量是函数内部定义的,对外部环境来说
局部变量是位于黑箱中的,不可见的,函数对齐局部变量有完全的、绝对的控制权。

然而还有一种变量,它既非外部环境给予的,也非函数内部自定义的,这种变量在函数执行期间
可以随意改变,它是自由的,对于函数来说,它是完全不受控制的(虽然你可以改变它的值,但是
它并不属于你),这种变量叫做自由变量。参数虽然也是可变的,但是一旦函数开始执行,
参数的值就是绑定好的,对函数而言参数的行为是可控的。

自由变量很难理解吗?其实不然,全局变量就是一种特殊的自由变量。

环境,context

一个函数,如果不存在任何自由变量,那么它就是一个纯粹的函数(pure function),此时它在任何
环境中的执行结果只依赖于它的参数,参数相同时执行结果一定是一样的。

但是,如果一个函数中存在自由变量,那么这个函数的执行结果不仅依赖于它的参数,还依赖于自由变量,
这个函数执行时必须要依附于一个环境(context),这个环境给它提供自由变量的值。注意这里的环境
指的是函数的运行环境而不是调用它的环境,也正是由于执行环境调用环境的分离导致闭包出现
了,

1
2
3
4
5
6
7
8
9
10
// 执行环境
function AddWith(x) {
return function(y) {
return x + y;
}
}

// 调用环境
var add2 = AddWith(2);
console.log(add2(1)); // 3

在函数(add2)被调用之前,它的执行环境(AddWith)已经结束了,但是它不能被销毁,否则add2就不能正确
执行了,因为它需要执行环境(AddWith)为其提供自由变量(x)。这个执行环境就称为闭包

那么对象呢?对象又是怎么回事儿?

我们完全可以把执行环境打包起来,专门为其中的函数提供自由变量值,我们成这个打包的执行环境为类,
称它里面的函数为方法,称自由变量为属性,而称执行环境的一个个实例为对象。

Master Foo之言

对象是富人的闭包,闭包是穷人的对象。

(over)