资讯专栏INFORMATION COLUMN

js-闭包

whidy / 3072人阅读

摘要:一闭包的概念闭包官方给出的解释闭包是函数和声明该函数的词法环境的组合。解决此类情况的方式使用立即执行函数使用中的这两种方式的共性就是把变量变成了每个函数的局部变量,因此在执行闭包的时候,局部变量不会发生变化。

一、闭包的概念

闭包官方给出的解释:闭包是函数和声明该函数的词法环境的组合。

下面我们举一个经典的且最简单的闭包demo

function closure(){
     var a=4;
     function clo(){
         console.log(a)
     }
     clo(); 
 }
 closure();

从上面的例子中,我们可以看出闭包需要的三基本个条件是:1.一个外层函数。2.一个内部函数。3.局部变量。

二、闭包的用途

要理解闭包的用途首先要理解javascript的特殊的变量作用域。

变量的作用域只有两种:全部变量和局部变量。而javascript语言中,函数内部可以直接读取全局变量,但是函数外部无法读取函数内部的局部变量。

而我们需要用到的闭包的场景就是:我们需要一个外部不可以直接访问一个函数内部变量的的环境。因此,通常你使用只有一个方法的对象的地方,都可以使用闭包。比如:插件封装,面向对象编程等。

闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于面向对象编程。在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。

1.DOM中使用闭包实例

12
14
16


function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + "px";
  };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);


document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;

2.用闭包模拟私有变量

 function closure2(){
    var pCounter=0;
    function changeBy(val){
      pCounter += val;
    }
    return{
        add:function(){
            changeBy(1)
        },
        reduce:function(){
            changeBy(-1)
        },
        value:function(){
           return pCounter
        }
    }
 }
 var counter1= closure2();
 var counter2 = closure2();
 console.log(Counter1.value());
 Counter1.add();
 Counter1.add();
 console.log(Counter1.value()); /* logs 2 */
 Counter1.reduce();
 console.log(Counter1.value()); /* logs 1 */
 console.log(Counter2.value()); /* logs 0 */

每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境。然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。

三、闭包的缺点

1.缺点一:变量发生变化

   function arr(){
           var res=new Array();
           for (var i = 0; i< 10; i++){
              res[i]=function(){
                  console.log(i);
              }
           }
           return res;
       }
      var arr1=arr();
      arr1[0]();//10
      arr1[1]();//10

因为闭包里面的函数调用发生在for循环结束之后,此时变量i的值是10,且res组成的闭包集合共用一个词法环境里面的变量i,因此每个闭包所输出的值都是10。

解决此类情况的方式:
a.使用立即执行函数

   function arr(){
        var res=new Array();
        for (var i = 0; i< 10; i++){
            res[i]=(function (num) {
                return function(){
                    console.log(num)
                }
            })(i)
        }
        return res;
      }
      var arr1=arr();
      arr1[0]();//0
      arr1[1]();//1

b.使用es6中的let

function arr(){
     var res=new Array();
     for (let i = 0; i< 10; i++){
        res[i]=function () {
                console.log(i)
        }
     }
     return res;   
   } 
   var arr1=arr();   
   arr1[0]();//0   
   arr1[1]();//1

这两种方式的共性就是把变量i,变成了每个函数的局部变量,因此在执行闭包的时候,局部变量i不会发生变化。

2.缺点二:this指向问题

   var obj = {
     name:"this",
      getName:function() {
         return function () {
             console.log(this.name)
         }
     }  
   }  
   var arr= obj.getName();  
   arr()//undefined

this指向当前调用函数的上下文,arr函数创建在全局环境中,所以在调用arr时,在非严格模式的浏览器环境中this指向window,在严格模式下this是undefined,而这两种情况下都没有一个全局的name,所以函数的执行结果为undefined。

3.缺点三:内存泄漏

function  showId() {
    var el = document.getElementById("div1")
    el.onclick = function(){
      console.log(el.id)   // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
}


// 改成下面
function  showId() {
    var el = document.getElementById("app")
    var id  = el.id
    el.onclick = function(){
      console.log(id)   // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
    el = null    // 主动释放el
}

当闭包中引用了全局变量时,记得在引用完之后进行释放,避免造成内存泄漏。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105069.html

相关文章

  • JS 中的闭包是什么?

    摘要:大名鼎鼎的闭包面试必问。闭包的作用是什么。看到闭包在哪了吗闭包到底是什么五年前,我也被这个问题困扰,于是去搜了并总结下来。关于闭包的谣言闭包会造成内存泄露错。闭包里面的变量明明就是我们需要的变量,凭什么说是内存泄露这个谣言是如何来的因为。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 大名鼎鼎的闭包!面试必问。请用自己的话简述 什么是「闭包」。 「闭包」的作用是什么。 首先...

    Enlightenment 评论0 收藏0
  • js闭包的本质

    摘要:也正因为这个闭包的特性,闭包函数可以让父函数的数据一直驻留在内存中保存,从而这也是后来模块化的基础。只有闭包函数,可以让它的父函数作用域永恒,像全局作用域,一直在内存中存在。的本质就是如此,每个模块文件就是一个大闭包。 为什么会有闭包 js之所以会有闭包,是因为js不同于其他规范的语言,js允许一个函数中再嵌套子函数,正是因为这种允许函数嵌套,导致js出现了所谓闭包。 function...

    qianfeng 评论0 收藏0
  • 谈谈我所理解的闭包js、php、golang里的closure

    摘要:当初看这个解释有点懵逼,理解成闭包就是函数中的函数了。里的闭包最近不满足于只干前端的活,开始用起了。里的闭包最近在学习语言,让我们来看一下语言里的闭包。在中,闭包特指将函数作为值返回的情况,被返回的函数引用了生成它的母函数中的变量。 本人开始接触编程是从js开始的,当时网上很多人说闭包是难点,各种地方对闭包的解释也是千奇百怪。如今开始接触js以外的各种编程语言,发现不光是js,php、...

    betacat 评论0 收藏0
  • 谈谈我所理解的闭包js、php、golang里的closure

    摘要:当初看这个解释有点懵逼,理解成闭包就是函数中的函数了。里的闭包最近不满足于只干前端的活,开始用起了。里的闭包最近在学习语言,让我们来看一下语言里的闭包。在中,闭包特指将函数作为值返回的情况,被返回的函数引用了生成它的母函数中的变量。 本人开始接触编程是从js开始的,当时网上很多人说闭包是难点,各种地方对闭包的解释也是千奇百怪。如今开始接触js以外的各种编程语言,发现不光是js,php、...

    zhoutao 评论0 收藏0
  • 详解js闭包

    摘要:但闭包的情况不同嵌套函数的闭包执行后,,然后还在被回收闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。每个函数,不论多深,都可以认为是全局的子作用域,可以理解为闭包。 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会...

    Chiclaim 评论0 收藏0
  • JS脚丫系列】重温闭包

    摘要:内部的称为内部函数或闭包函数。过度使用闭包会导致性能下降。,闭包函数分为定义时,和运行时。循环会先运行完毕,此时,闭包函数并没有运行。闭包只能取得外部函数中的最后一个值。事件绑定种的匿名函数也是闭包函数。而对象中的闭包函数,指向。 闭包概念解释: 闭包(也叫词法闭包或者函数闭包)。 在一个函数parent内声明另一个函数child,形成了嵌套。函数child使用了函数parent的参数...

    MartinDai 评论0 收藏0

发表评论

0条评论

whidy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<