1、闭包
1、如何产生闭包?
一个嵌套的函数,其子函数引用了父函数的变量或函数时,就产生了闭包。
function a(){
var name = 'suzy';
function b(){ // 执行函数定义就可产生闭包,无需调用内部函数。
console.log(name)
}
return b
}
a()
2、常见的闭包
// 将子函数作为父函数的返回值
function a(){
var num = 0;
function b(){
num ++;
console.log(num)
}
return b
}
var aaa = a()
aaa() // 1
aaa() // 2
aaa() // 3
// 将函数的实参传递给另一个函数调用
function fun1(msg, time) {
setTimeout(function() {
console.log(msg)
}, time)
}
fun1('hello', 1000)
3、闭包的作用
1、函数外部可以操作或访问到函数内部的变量。
2、延长了局部变量的生命周期(闭包内引用的函数外部的变量依然存在内存中,没有被垃圾回收)
问题:
1、函数执行完后,函数内声明的变量是否还存在? (一般不存在了,存在于闭包中的变量才有可能存在)
2、再函数外部能直接访问函数内部的局部变量嘛?(不能,但我们可以通过闭包让外部操作它。)
4、闭包的生命周期
产生:在嵌套内部函数定义执行完成时就产生了(不是在调用)
死亡:再嵌套的内部函数成为垃圾对象时
5、闭包的应用
// myModules.js
(function(window) {
// 传window的好处:代码压缩时,window可以简写成w
var msg = 'Hello';
function lowerCase() {
console.log(msg.toLowerCase())
}
function upperCase() {
console.log(msg.toUpperCase())
}
window.myModule = {
lowerCase: lowerCase,
upperCase: upperCase
}
})(window)
// demo.html
<script src="myModule.js"></script>
<script type="text/javascript">
// "use strict";
myModule.upperCase() // HELLO
myModule.lowerCase() // hello
</script>
6、闭包的缺点
缺点:
1、函数执行完后,函数内部的局部变量没有释放,占用内存时间会变长。
2、容易照成内存泄露
(解决:及时释放)
7、内存溢出 与 内存泄露
1、内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时,就会抛出内存溢出的错误。
2、内存泄露
- 占用的内存没有及时释放
- 内存泄露累计多了就容易导致内存溢出
- 常见的内存泄露(意外的全集变量:a = 10,没有及时清理的计时器或回调函数、闭包)
var obj = {}
for (var i = 0; i < 1000; i++) {
obj[i] = new Array(10000000)
}
console.log(obj) // 此时程序会报内存溢出的错
2、闭包高级面试题
var name = 'suzy'
var object = {
name:'hello',
getName:function(){
var that = this;
return function(){
console.log(this.name) // suzy
console.log(that.name) // hello
}
}
}
object.getName()()
// 看懂下面的代码,闭包的任何问题都难不倒你。
function fun(n, o) {
console.log(o)
return {
fun: function(m) {
return fun(m, n)
}
}
}
var a = fun(0);
a.fun(1)
a.fun(2)
a.fun(3)
// undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3)
// undefined,0,1,2
var c = fun(0).fun(1);
c.fun(2)
c.fun(3)
// undefined,0,1,1
来源:CSDN
作者:suzyCai
链接:https://blog.csdn.net/weixin_42080477/article/details/103463085