简介
作用域是一个变量和函数的作用范围,例如javascript中函数内声明的所有变量在函数体内始终是可见的,在javascript中有全局作用域和局部作用域。外部作用域是相对当前作用域而言的,外部作用域一般指的是外部函数中变量作用域。因为在执行一个函数时可能需要引用其他函数中的变量,一般都是通过闭包来实现调用,原因主要是隐藏和保护外部作用域执行上下文。
变量在程序设计中,变量(Variable,scalar)是指一个包含部分已知或未知数值或资讯(即一个值)之储存位址,以及相对应之符号名称(识别字)。通常使用变数名称参照储存值;将名称和内容分开能让被使用的名称独立于所表示的精确讯息之外。在定义了一个变量以后,并不是在 程序的任何地方都可以使用这个变量。只有在变量的作用域内才能使用这个 变量。在C语言中如果按作用域分,变量分为局部变量和全局变量。
局部变量在一个函数内部定义的变量被称作局部变量,这种变量的作用域是在本 函数范围内。通俗一点说,局部变量只能在定义它的函数内部使用,而不能 在其它函数内使用这个变量。
说明:
1、main函数也是一个函数,它内部定义的变量也只能在main函数内部使用, 而不能在其它函数内部使用main函数内部定义的变量。
2、不同的函数中可以使用相同的变量名,但它们是不同的变量。记得 数在执行时,系统要给它分配一块单独的内存吗?所以虽然变量是一样的, 但系统看到它们定义在不同的函数中,就认为它们是不同的变量。这样做有 个好处,可以在函数内部,根据需要设置任何的变量名。如果不是这样,那 么在一个函数内定义了一个变量名后,在其它函数内就不能再使用相同的变 量名了。
3、形参也属于局部变量,作用范围在定义它的函数内。所以在定义形参 和函数体内的变量时是肯定不能重名的了。
4、在复合语句内部也可以定义变量,这些变量的作用域只在本复合语句 中。只在需要的时候再定义变量,这样做可以提高内存的利用率。1
全局变量在函数外部定义的变量称作外部变量,外部变量属于全局变量。全局变 量的作用域是从定义变量的位置开始到本源文件结束。这样全局变量可以让 很多函数都使用它。
说明:
1、在一个函数内部,即可以使用本函数定义的局部变量,也可以使用 在此函数前定义的全局变量。在上面的例子中,main函数和f2函数中可以使 用全局变量a,b,x,y,而在f1函数内只能使用全局变量x,y。
2、全局变量的作用是使得函数间多了一种传递信息的方式。如果在一 个程序中各个函数都要对同一个信息进行处理,就可以将这个信息定义成全 局变量。另外,采用这种方式,可以从某个函数内部得到多个计算值
3、全局变量的作用范围是从定义位置起直到程序结束处。如果想在定义 全局变量的前面直接使用全局变量是不可能的。如果就是想用,就将全局变 量的定义往前写一写。另外还有一种方法,不用改变全局变量的定义位置, 就是在要使用全局变量的函数内使用extern关键字对要使用的全局变量说明一 下,告诉系统,我要使用的这个变量可是全局变量啊!
4、如果在一个函数内部,一个局部变量和一个全局变量重名,那么是局 部变量起作用。而外部变量不起作用。
闭包概述在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
彼得·兰丁 在1964年将术语 闭包 定义为一种包含 环境成分 和 控制成分的实体,用于在他的SECD 机器上对表达式求值。 Joel Moses 认为是 Landin 发明了 闭包 这一术语,用来指代某些其开放绑定(自由变量)已经由其语法环境完成闭合(或者绑定)的 lambda 表达式,从而形成了 闭合的表达式,或称闭包。这一用法后来于 1975 年被 Sussman 和 Steele 在定义 Scheme 语言的时候予以采纳。并广为流传。2
用途因为闭包只有在被调用时才执行操作(暂且不论用于生成这个闭包对象本身的开销,比如 C++ 中按值捕获意味着执行复制构造函数),即“惰性求值”,所以它可以被用来定义控制结构。例如:在Smalltalk语言中,所有的控制结构,包括分歧条件(if/then/else)和循环(while和for),都是通过闭包实现的。用户也可以使用闭包定义自己的控制结构。
多个函数可以使用一个相同的环境,这使得它们可以通过改变那个环境相互交流。比如在Scheme中:
(define foo #f)
(define bar #f)
(let ((secret-message "none"))
(set! foo (lambda (msg) (set! secret-message msg)))
(set! bar (lambda () secret-message)))
(display (bar)) ; prints "none"
(newline)
(foo "meet me by the docks at midnight")
(display (bar)) ; prints "meet me by the docks at midnight"
闭包可以用来实现对象系统。3