- A+
所属分类:Web前端
闭包理解
如何产生闭包
- 当一个嵌套的内部(子)函数引用了嵌套外部(父)函数的变量(函数)时--就产生了闭包
闭包是什么
-
使用chrome调试查看
-
理解一 -- 闭包是嵌套的内部函数
-
理解二 -- 闭包是包含被引用变量(函数)的对象
-
闭包存在于嵌套的内部函数中
-
产生闭包的条件
-
函数嵌套
-
内部函数引用了外部函数的数据(变量或函数)
<script> function fn1() { var a = 3; function fn2() { console.log(a); } fn2(); } fn1(); </script>
常见闭包
将函数作为另一个函数的返回值
function fn1() { var a = 2; function fn2() { a++; console.log(a); } return fn2; } var f = fn1(); f(); //3--fn1的返回值是fn2--相当于调用了fn2()--相当于fn1()() f(); //4--闭包不会消失--第一次fn1()执行时--闭包内的数据是3--第二次执行时就是4
将函数作为实参传递给另一个函数调用
function showDelay(msg, time) { setTimeout(function () { console.log(msg); //闭包 }, time); } showDelay('zao', 2000);
闭包的作用
-
使用函数内部的变量在函数执行完后--仍然存活在内存中--延长了局部变量的生命周期
-
让函数外部可以操作(读写)到函数内部的数据--变量/函数
问题
- 函数执行完--函数内部声明的局部变量是否还存在--一般不存在,存在于闭包中的变量才可能存在
- 在函数外部能直接访问函数内部的局部变量吗--不能,但可以通过闭包让外部操作它
闭包的生命周期
- 产生--在嵌套内部函数定义执行完时就产生了
- 死亡--在嵌套内部函数成为垃圾对象时
function fn1(){ // 闭包产生--函数提升--内部函数已经创建了 var a = 2; function fn2(){ a++; console.log(a); } return fn2; } //只要有变量引用fn1()闭包就一直存在 var f = fn1(); f(); f(); //闭包死亡--包含闭包的函数成为垃圾对象 f = null;
闭包的应用
定义JS模块
- 具有特定功能的js文件
- 将所有数据和功能都封装在一个函数内部--私有
- 只向外暴露一个包含n个方法的对象或函数
- 模块的使用者--只需通过模块暴露的对象调用方法来实现对应的功能
//JS文件 function myMoudle() { var msg = 'zaoya'; function doSomething() { //toUpperCase--字符串转换为大写 console.log('doSomething()' + msg.toUpperCase()); } function doOtherthing() { //toLowerCase--字符串转换为小写 console.log('doOtherthing()' + msg.toLowerCase()); } //向外暴露对象 return { doSomething: doSomething, doOtherthing: doOtherthing } } //html文件 <script src="myMoudle.js"></script> <script> let fn = myMoudle(); fn.doSomething(); fn.doOtherthing(); </script>
//JS文件 (function myMoudle1() { let msg = 'zaozao'; function doSomething() { console.log('doSomething()' + msg.toUpperCase); }; function doOtherthing() { console.log('doOtherthing()' + msg.toLowerCase); } window.myMoudle1 = { doSomething: doSomething, doOtherthing: doOtherthing } })() //html文件 <script src="myMoudle1.js"></script> <script> myMoudle1.doSomething(); myMoudle1.doOtherthing(); </script>
闭包的缺点
缺点
- 函数执行完后--函数内的局部变量没有释放--占用内存时间会变长
- 容易造成内存泄漏
解决
- 能不用闭包就不用闭包
- 及时释放
内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时--就会抛出内存溢出的错误
内存泄漏
- 占用的内存没有及时释放
- 内存泄漏积累多了就容易导致内存溢出
常见内存泄漏
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包
面试题
var name = 'The Window'; var object = { name: 'My Object', getNameFunc: function () { return function () { return this.name; } } } //object.getNameFunc()--是对象调用--通过object调用--this为object //通过object.getNameFunc()--调用函数--object.getNameFunc()()--是函数调用--this为window alert(object.getNameFunc()()); //The Window var name2 = 'The Window'; var object = { name2: 'My Object', var that = this; return function () { return that.name2; } } } //object.getNameFunc()--是对象调用--通过object调用--this为object //object.getNameFunc()()--中that是object.getNameFunc()的this--指向object alert(object.getNameFunc()()) //My Object