前端总结(一)闭包

一、对闭包的理解,以及哪些地方用过闭包,以及闭包的缺点。

闭包(closure)是javascript的一大难点,也是它的特色。很多高级应用都要依靠闭包来实现。

(1)变量作用域

javascript的变量作用域只有两种:全局变量和局部变量。

javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

注意:在函数内部声明变量的时候,一定要使用var命令。否则,默认的会添加到全局对象的属性上去,即声明的是全局变量!

(2)如何从外部读取函数内部的局部变量?

但我们有时候需要获取到函数内部的局部变量。上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。

那就是在函数内部,再定义一个函数。

function f1(){
    var n=999;
    function f2(){
      alert(n); // 999
    }
}

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。

这就是Javascript语言特有的"链式作用域"结构(chain scope),

子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

(3)闭包的概念

上面代码中的f2函数,就是闭包。

理解1: 闭包就是能够读取其他函数内部变量的函数

理解2:闭包就是有权访另一个函数作用域中变量的函数。

由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。

所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

(4)闭包的特点

函数嵌套函数; 
函数内部可以引用函数外部的参数和变量; 
函数变量和参数不会被垃圾回收机制回收;

(5)闭包的优缺点

优点 
- 希望一个变量长期驻扎在内存中 
- 避免全局变量的污染 
- 私有成员的存在 

缺点 
- 常驻内存,增大内存使用量,使用不当回造成内存泄漏;

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

 (6)闭包的用途

闭包一般的用途在,轮播、幻灯片,通过闭包记住点击的index。

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

二、闭包

 

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

 

闭包的特性:1.函数内再嵌套函数2.内部函数可以引用外层的参数和变量3.参数和变量不会被垃圾回收机制回收//li节点的onclick事件都能正确的弹出当前被点击的li索引

<ul id="testUL">
<li> index = 0</li>
<li> index = 1</li>
<li> index = 2</li>
<li> index = 3</li>
</ul>
<script type="text/javascript">
 var nodes = document.getElementsByTagName("li"); 
for(i = 0;i<nodes.length;i+= 1){
nodes[i].onclick = (function(i){ 
return function() {
console.log(i);
} //不用闭包的话,值每次都是4 })(i);
}
</script>

执行say667()后,say667()闭包内部变量会存在,而闭包内部函数的内部变量不会存在
使得Javascript的垃圾回收机制GC不会收回say667()所占用的资源
因为say667()的内部函数的执行需要依赖say667()中的变量
这是对闭包作用的非常直白的描述 function say667() { // Local variable that ends up within closure
var num = 666; var sayAlert = function() {
alert(num);
}
num++; return sayAlert;
} var sayAlert = say667();
sayAlert()//执行结果应该弹出的667

三、介绍一下闭包和闭包常用场景?

 

  • 使用闭包主要为了设计私有的方法和变量,闭包的有点事可以避免变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念。
  • 闭包有三个特性:
    • 函数嵌套函数
    • 函数内部可以引用外部的参数和变量
    • 参数和变量不会被垃圾回收机制回收
  • 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见方式,就是在一个函数的内部创建另一个函数
    • 应用场景,设置私有变量的方法
    • 不适用场景:返回闭包的函数是个非常大的函数
    • 闭包的缺点就是常驻内存,会增大内存使用量,使用不当会造成内存泄漏

 

四、为什么会出现闭包这种东西?解决了什么问题?

受javascript链式作用域链的影响,父级变量中无法访问到子级的变量值

 

posted @ 2019-02-22 11:18  小杜村  阅读(437)  评论(0编辑  收藏  举报