为了账号安全,请及时绑定邮箱和手机立即绑定

Javascript 闭包

1.理解闭包

    1.1 如何产生闭包?

        当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包

    1.2 闭包到底是什么?

        i:闭包是嵌套的内部函数

        ii:包含被引用变量(函数)的对象

        iii:闭包存在于嵌套的内部函数中

    1.3 产生闭包的条件:

        i:嵌套的函数

        ii:内部函数引用了外部函数的数据(变量/函数)

 function foo(){    
   var a = 1;    
   function bar(){
     //内部函数bar引用了外部函数foo的a变量,此时产生闭包   
     console.log(a);    
   }
   bar()  
 }  
 foo();

2.常见的闭包

    2.1 将函数作为另一个函数的返回值

function fn1(){  
  var a = 1;  
  function fn2(){    
    a++;    
    console.log(a);  
  }  
  return fn2
}
var fn = fn1();//产生闭包,变量a = 1
fn() //2
fn() //3

    2.2 将函数作为实参传递给另一个函数调用

function delay(msg, time){  
  setTimeout(function(){    
    alert(msg)  
  }, time)
}
delay('Hello Closure', 1000)

3.闭包的作用

    3.1 使用函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)

    3.2 让函数外部可以操作(读/写)到函数内部的数据(变量/函数)

4.闭包的生命周期

    4.1 产生:在嵌套的内部函数定义执行完成时就产生了(不是在调用)

    4.2 死亡:在嵌套的内部函数成为垃圾对象时

function foo(){  
  //此时闭包已经产生(函数提升,内部函数已经创建)    
  var a = 1;    
  function bar(){      
    console.log(a);    
  }    
  return bar;  
}
var f = foo();
f()
f = null //闭包死亡(包含闭包的函数成为垃圾对象)

5.闭包的使用:自定义JS模块

(function (window){  
  //私有数据  
  var msg = "Hello closure";  
  function doSomething() {    
    console.log("doSomething() "+msg.toUpperCase());  
  }  
  function doOtherthing() {    
    console.log("doOtherthing() "+msg.toLowerCase());  
  }  
  //向外暴露对象  
  window.module = {    
    doSomething:doSomething,    
    doOtherthing:doOtherthing  
  }
})(window)
module.doSomething(); //doSomething() HELLO CLOSURE
module.doOtherthing(); //doOtherthing() hello closure

6.闭包的缺点及解决

    6.1 缺点:

        i:函数执行完后,函数内的局部变量没有释放,占用内存时间会变长

        ii:容易造成内存泄漏

    6.2 解决:

        i:能不用闭包就不用

        ii:及时释放

function fn1() {  
  var ary = new Array(100000);  
  function  fn2() {    
   console.log(ary)  
  }  
  return fn2;
}
var fn = fn1()
fn()
fn = null; //让内部函数成为垃圾对象-->回收闭包

补充知识点:

    1.内存溢出

        i:一种程序运行出现的错误

        ii:当程序运行需要的内存超过了剩余内存时,就抛出内存溢出的错误

    2.内存泄漏

        i:占用的内存没有及时释放

        ii:内存泄漏积累多了,容易导致内存溢出

        iii:常见的内存泄漏:意外的全局变量,没有及时清理的定时器或者回调函数,闭包

//内存溢出
var obj = {};
for(var i = 0; i < 10000; i++){  
  obj[i] = new Array(1000000)
}
//浏览器报错:显示此网页时内存不足
//内存泄漏
//意外的全局变量
function fn() {  
  ary = new Array(100000)  
  console.log(ary)
}
fn()

//没有及时清理的定时器或者回调函数
var intervalId = setInterval(function() {  
  console.log("hello closure")
}, 1000)
clearInterval(intervalId) //清除定时器

//闭包
function fn1() {  
  var ary = new Array(100000);  
  function fn2() {    
    console.log(ary)  
  }  
  return fn2;
}
var fn = fn1()
fn()

 面试题1

//code1 
var name = "outside" 
var obj = {   
  name:"inside",   
  getNameFunc:function(){     
    return function(){       
      return this.name     
    }
  } 
} 
alert(obj.getNameFunc()()) //? 是否有闭包? 

//code2 
var name = "outside" 
  var obj = {   
  name:"inside",   
  getNameFunc:function(){     
    var that = this;     
    return function(){       
      return that.name     
    }   
  } 
} 
alert(obj.getNameFunc()()) //? 是否有闭包

面试题2

function foo(v1, v2){  
  console.log(v2);  
  return {    
    foo:function(v3){      
      return foo(v3, v1);    
    }  
  }
}
var a = foo(0); a.foo(1); a.foo(2); a.foo(3) //?
var b = foo(0).foo(1).foo(2).foo(3)//?
var c = foo(0).foo(1); c.foo(2); c.foo(3)//?

PS:面试题答案参考评论区

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
53
获赞与收藏
488

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消