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:面试题答案参考评论区
共同学习,写下你的评论
评论加载中...
作者其他优质文章