去年就嚷嚷写博客了,结果学前端那么久,都没有把自己心得体会在优快云里写下来,全记在印象笔记里了。现在重温笔记,就慢慢把它转移到这吧,不过自己的经验太少太菜,所以还是停留在很基础的部分,目的想要把遇到的坑都记录下来。
强大的闭包
第一篇就说说JS里面强大的闭包吧。在我刚学前端的时候,自不量力去面试前端实习生的时候,被面试官问到一个问题,就是——“你知道什么是闭包吗?”
我思考了下,“不就是函数么”,“那,你写一个闭包给我看看”
我当时还真就写了一个function
当时真是特别傻,不过JavaScript权威指南里确实是在函数这章里介绍的闭包,通俗的说,所有JavaScript里的function都是一个闭包,不过并不能体现我们说的强大的闭包。
作用域
我们都知道JavaScript是弱类型语言,所以相对其他面向对象的语言,它真是很好理解对象这个概念,就是万物皆对象,所有函数也是对象。Javascript语言还有一个特殊之处,就在于函数内部可以直接读取全局变量。我们也知道,局部变量在函数执行结束时会自动消解,函数外部无法读取。
var n=100;
function f1(){
alert(n);
}
f1(); // 100
function f2(){
var n=100;
alert(n);
}
f2();//error 注意如果函数内声明的变量不带var的话,其实表示的是n为全局变量
所以可以推论,如果一个函数嵌套一个子函数,父函数的局部变量对于子函数是可见的,而子函数的局部变量对于父函数是不可见的,子函数属于在父函数的作用域内。这就是JavaScript常说的“作用域链”。子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
所以,如果把子对象作为返回值,那岂不可以在函数外部访问到内部变量了吗。于是,我们常见的闭包是这样的:
function f1(){
var n=100;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result();// 100
因为f1()对象返回的是内部函数f2,所以在这段代码中内部函数f2被赋给了全局对象result,所以f2始终存在于内存中,而f2依赖于f1,所以f1也不会被当垃圾回收掉,f2所引用的内部变量一直存在于内存中不会被回收。
这就是我们常说的闭包:当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们。
闭包的作用
既然那么奇妙,所以通常在这些场景的时候可以想到用它
- 保护函数内变量安全。//外部函数的变量只有内部函数才能引用,没有别的途径可以引用哦。
- 在内存中维持一个变量。//还定义全局变量就low了。
- 通过保护变量安全来实现JS私有属性和私有方法。
原来觉得闭包好绕好难懂,所以尽量避免用它,但后面慢慢学习写jquery插件的时候,发现真的——学前端怎么可以不懂闭包
避免闭包滥用内存
既然闭包可以由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。例如
function f1(){
var n=100;
return function f2(){
return n;
}
n=null;//释放内存
}
好吧,没有深入继续讲闭包….下次吧。
本文从作者学习前端的经历出发,详细介绍了JavaScript中的闭包概念及其应用场景。解释了闭包如何帮助保护函数内的变量安全,并维持变量在内存中的持久存在。
3万+

被折叠的 条评论
为什么被折叠?



