闭包的存储
① JavaScript中的闭包是用来做什么的
闭包有两个作用,一是外部可以读取函数内部的变量
functionf1(){
n=999;
functionf2(){
alert(n);
}
returnf2;
}
varresult=f1();
result();//999
另一个就是让这些变量的值始终保持在内存中
functionf1(){
varn=999;
nAdd=function(){n+=1}
functionf2(){
alert(n);
}
returnf2;
}
varresult=f1();
result();//999
nAdd();
result();//1000
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个
匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
其应用场景就是:
函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
在内存中维持一个变量
通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)
私有属性和方法在Constructor外是无法被访问的
② 怎样理解“闭包”
闭包是可以包含自由(未绑定)变量的代码块;这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量的存在,相关变量引用没有释放)和为自由变量提供绑定的计算环境(作用域)。在 Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby 和 Python 等语言中都能找到对闭包不同程度的支持。
闭包的价值在于可以作为函数对象 或者匿名函数,对于类型系统而言这就意味着不仅要表示数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中、作为参数传递给其他函数,最重要的是能够被函数动态地创建和返回。
③ 闭包是用来做什么的(js)
闭包是指有权访问另外一个函数作用域中的变量的函数。
闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。
作用是:匿名自执行函数:我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。
结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
④ swift 什么情况下使用闭包
闭包是功能性自包含模块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其他一些编程语言中的 lambdas 比较相似。
闭包可以 捕获 和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift会为您管理在 捕获 过程中涉及到的内存操作。
注意:如果您不熟悉 捕获 (capturing) 这个概念也不用担心,后面会详细对其进行介绍。
在Swift函数章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:
全局函数是一个有名字但不会捕获任何值的闭包
嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字的闭包
Swift的闭包表达式拥有简洁的风格,并鼓励在常见场景中以实现语法优化,主要优化如下:
利用上下文推断参数和返回值类型
单表达式(single-expression)闭包可以省略 return 关键字
参数名称简写
Trailing 闭包语法
⑤ php如何序列化/存储闭包(Closure)
实在需要序列化,可以用反射(Reflection),并直接操作代码文件获得上下文信息:/*** 创建一个反射:*/$reflection = new ReflectionFunction($closure);/*** 参数可以直接得到了:*/$params = $reflection-getParameters();/*** 获得Closure的函数体和use变量,形如: * function($arg1, $arg2, ...) use ($val1, $val2, ...) { * // 要获得这个部分的代码!* }* 办法很多,你可以直接用正则、字符串查找或者Tokenizer,等等等等。 * 比如可以先从reflection里得到函数的开始行和结束行:*/$startLine = $reflection-getStartLine(); $endLine = $reflection-getEndLine(); // 然后用str*这个,str*那个的函数来清理,细节不写了:
⑥ 为什么JavaScript闭包能保存变量在内存中
因为返回了一个内部引用,这个内部引用又引用了变量,所以变量在内存中,如
function a(){
var i = 0;
function b(){
alert(i++);
}
return b;
}
var c = a();
c();
c();
手写的代码,不保证正确