作用域
在程序的某个节点上的作用域指的是,该代码节点能够阅读到的所有实体(entity),也被称为上下文或者执行环境。
(注:entity简单来讲就是由标识符代表的代码和变量)
词法作用域与动态作用域
以上我们提到作用域的讨论依赖具体的程序节点,这个程序节点可以细分为如下两块。
- lexical scope(词法作用域):源代码的文本片段(area of text)
- dynamic scope(动态作用域):源代码的节点运行时(runtime)
词法作用域(静态作用域)是在书写代码或者说定义时确定的,而动态作用域是在运行时确定的。
词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用,其作用域链是基于运行时的调用栈的。
词法作用域执行方式
词法作用域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,去函数定义时的环境中查询。
动态域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,到函数调用时的环境中查。
闭包在语言中的实现方式
要实现闭包,在数据结构选型方面,肯定不是线性stack,因为闭包在执行时,仍应该保持绑定上下文的不变,而不是去阅读对应的执行环境。而线性(stack)显然无法满足要求。
实际上对于大部分拥有闭包的语言,程序语言采用的是堆(heap)的形式存储上下文non-local变量。 也正因为如此,这些语言基本自带GC(垃圾回收)。
闭包的形成需要两个条件
-
在函数内部创建新的函数
-
新的函数在执行时,访问了函数的变量对象
结论
- 闭包是词法作用域在函数式编程语言的集中体现。(闭包的形成,与作用域链的访问顺序有直接关系。)
- 在实践上,闭包就是函数和上下文的绑定。(只有内部函数访问了上层作用域链中的变量对象时,才会形成闭包)
- 闭包允许闭包内的函数,访问闭包创建时拷贝的上下文变量(值或者引用)。
网友评论