js——函数的闭包

两个函数互相嵌套或者多个函数互相嵌套----闭包

闭包是指有权访问另一个函数的作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数。

但凡是内部的函数保存在了外部,一定产生闭包。


关于内存泄露问题

当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放(占空间),造成内存泄漏

内存泄漏:占用的内存没有及时释放。内存泄露积累多了就容易导致内存溢出。

常见的内存泄露

  1. 意外的全局变量
  2. 没有及时清理的计时器或回调函数
  3. 闭包
情况一举例:

 // 意外的全局变量
  function fn() {
      a = new Array(10000000);
      console.log(a);
  }
  fn();
  
  情况二举例:
  
   // 没有及时清理的计时器或回调函数
  var intervalId = setInterval(function () { //启动循环定时器后不清理
      console.log('----')
  }, 1000)

  // clearInterval(intervalId);  //清理定时器
  
  情况三举例:
  
  function fn1() {
  var arr = new Array[100000];   //这个数组占用了很大的内存空间
  function fn2() {
    console.log(arr.length)
  }
  return fn2
}
var f = fn1()
f()

f = null //让内部函数成为垃圾对象-->回收闭包

内存泄漏解决方法:

能不用闭包就不用,及时释放

f=null; // 让内部函数形成对象垃圾,回收闭包

function a(){
    
    var num=100;
    function b(){
        num++;
        console.log(num);
    }
    return b; 
}
//把 b return出去之后(b到了全局),a算执行完了
var demo=a(); 
demo(); //b执行 // 101
demo(); // 102

function compare(){
    if(value1<value2){
        return -1;
    }else if(value1>value2){
        return 1;
    }else{
        return 0;
    }
}

当创建compare()函数时,会创建一个预先包含全局变量对象的作用域,这个作用域被保存在内部的[[scope]]属性中,当调用这个compare()函数时,会为函数创建一个执行环境,然后通过复制函数的[[scope]]属性中的对象构建起执行环境的作用域链。此后,又有一个活动对象被创建并被推入执行环境的作用域链的前端。compare()作用域链包含两个变量对象:本地活动对象,全局活动对象


多个函数和一个函数形成闭包,他们之间的变量可以共用


闭包作用

  1. 实现公有变量

eg:不依赖外部变量并且能反复还行的函数累加器

function add(){
    var count=0;
    function demo(){
        count++;
        console.log(count);
    }
    return demo;
}

var counter=add();
counter();
counter();
counter();
counter();

每调用一次,就在原有基础上加1
  1. 可以做缓存(存储结构)
function test(){
    var food="apple";
    var obj={
        eatFood:function(){
            if(food!=""){
                console.log("I am eating "+food);
                food="";
            }else{
                console.log("There is nothing");
            }
        },
        pushFood:function (myFood){
            food=myFood;
        }
    }
    return obj;
}

var person=test();

person.eatFood(); // I am eating apple
person.eatFood();  // There is nothing
person.pushFood("banana");
person.eatFood(); // I am eating banana
  1. 可以实现封装,属性私有化
//立即执行函数解决闭包作用域的问题
function test(){
    var arr=[];
    for(var i=0;i<10;i++){
    (function(j)
        arr[j]=function(){
            console.log(j); //定义不执行
        }(i))
    }
    return arr;
}

var myArr=test();
for(var j=0;j<10;j++){
    myArr[j]();
}
//这是个函数都和test形成闭包

私有化变量:只有通过自己的方法才能访问,外部不能访问。

function Deng(name,wife){
    var prepareWife="xiaozhang";
    
    this.name=name;
    this.wife="xiaoliu";
    this.divorce=function(){
        this.devorce=prepareWife;
    }
    this.changePrepareWife=function (target){
        prepareWife=target;
    }
    this.sayPrepareWife=function(){
        console.log(prepareWife);
    }
}

var deng=new Dend('deng','xiaoliu');

console.log(deng.prepareWife); //undefined(外部访问)
console.log(deng.sayPrepareWife()); // xiaozhang(通过自己的方法访问)
  1. 模块化开发,防止污染全局变量【命名空间】

闭包的应用:

  • 具有特定功能的js文件
  • 将所有的数据和功能都封装在一个函数内部(私有的)
  • 【重要】只向外暴露一个包含n个方法的对象或函数
  • 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
方式一:

function my(){
    //私有数据
    var msg="Smyhvae Haha";
    
    //操作私有数据的函数
    function dosomething(){
        console.log("dosomething()"+msg.toUpperCase());
    }
    
    function doOtherthing(){
        console.log('doOtherthing()'+msg.toLowerCase());
    }
    
    //通过【对象字面量】的形式进行【包裹】,向外暴露多个函数
    return{
        dosomething1:doSomething,
        doOtherthing:doOtherthing
    }
}

在html文件中

var module=my();
module.dosomething1();
module.doOtherthing2();


方式二

(function(){
     //私有数据
    var msg = 'Smyhvae Haha'

    //操作私有数据的函数
    function doSomething() {
        console.log('doSomething() ' + msg.toUpperCase())
    }

    function doOtherthing() {
        console.log('doOtherthing() ' + msg.toLowerCase())
    }
    
    //外部变量是立即执行运行的匿名函数,我们可以把两个方法直接传给window对象
    window.mymodule={
        dosomething1=doSomething,
        doOthing2:doOtherthing
    }
}())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值