大家需要记住一句话:函数的作用域与他定义的位置有关,与调用位置无关。
今天让我们来学习闭包吧
一、JS的内存管理 JS对于基本数据类型内存的分配,会在执行时,直接在栈空间进行分配。JS对于复杂数据类型内存的分配,会在堆内存中开辟一块空间,并且将这块空间的指针返回值变量引用;
二、JS的垃圾回收(Garbage Collection->GC)
js中时有垃圾回收机制的(当然像c和c++就没得,这里不多赘述),因为内存的大小是有限的,当内存不再需要的时候,我们就需要对其进行释放。像那些不再使用的对象,我们都称之为是垃圾,它就会被回收。
2.1常见GC算法 引用计数。像我们上面的图那样,堆结构中的obj是有个箭头指向他的,所以他就是被引用的,有一个引用,计算器就+1(会存在循环引用的问题),如果你想手动清除,可以把obj=null标记清除(JS引擎比较广泛的采用的就是标记清除算法,不会存在循环引用的问题),如下图的m,n就是会被清除的 ,根就是GO三、闭包
为什么我们在讲闭包前,还要讲js的内存,因为闭包里是可能会有内存泄漏的问题,所以先给大家说了下js的内存是如何管理的。
在js中函数是非常重要的,并且是一等公民,那么函数的使用就是非常灵活的,可以作为另外一个函数的参数,也可以作为另外一个函数的返回值来使用。
维基百科的解释:
闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures)。是在支持 头等函数 的编程语言中,实现词法绑定的一种技术。闭包在实现上是一个结构体,它存储了一个函数和一个关联的环境(相当于一个符号查找表)。闭包跟函数最大的区别在于,当捕捉闭包的时候,它的 自由变量 会在补充时被确定,这样即使脱离了捕捉时的上下文,它也能照常运行;MDN的解释:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。 3.1标准闭包
function foo() {
var name = 'foo'
function bar() {
console.log(111, name);
}
return bar
}
var fn = foo()
fn()
看上面的代码就是严格意义上的闭包,因为按照正常来讲,当var = foo() 执行完时,意味着foo中的var name = “foo”是应该被销毁的,但是很明显在执行fn()时,name是还可以访问的,。也就是说:我们在捕捉bar这个函数时,name这个变量也被一起捕捉了,他两一起就形成了闭包,这也契合了维基百科的解释。
3.2广义的闭包var a = 1
function foo() {
console.log(a);
}
foo()
我们来看这段代码,大家觉得这是不是个闭包,我觉按照上面的官方定义这个也是闭包,因为他有函数也可以访问自由变量。
function foo() {
}
那我们再看,这个呢?这个的争议就比较大了,因为从可以访问自由变量的角度来说,他当然是可以的,他也是个函数,所以我们也已认为他是闭包。
3.2闭包总结 闭包由两部分组成:函数+可以访问的自由变量 也就是说:一个普通的函数,如果它可以访问外层作用域的自由变量,那么这个函数就是一个闭包。从广义的角度来说:JavaScript中的函数都是闭包。从狭义的角度来说:JavaScript中一个函数,如果访问了外层作用域的变量,那么它是一个闭包。 四、代码执行过程加深下大家对代码执行过程的理解
var message = '111'
function foo() {
var name = "foo"
}
function bar() {
console.log("bar")
}
foo()
test()
1.解析
2.开始执行
var message = ‘111’ 所以GO中的message变成‘111’
接下来是foo() 此时又会开始解析foo
函数的解析会先创建 函数执行上下文,生成AO对象,函数中的VO就是AO
3.foo解析完成才开始执行foo,执行这里就不画了,这里就是把AO中的name变为‘foo’
4. foo执行完成,销毁函数上下文(此时没有指针指向AO所以AO也销毁了)
5.开始执行bar()这里就不画了 因为是同样的先解析bar在执行,在销毁。
定义:该被销毁的AO,却始终都没有被销毁,此时就造成了内存泄露。(为什么没被销毁,肯定是有指针一直指着他,所以无法销毁)
怎么解决呢? 很简单,将其设置为null。
当然要不要将其设置为null,取决于我们还会不会用,如果我们还要用,那就没必要手动销毁它了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)