一.定义
所谓的闭包,现在已经基本不使用了
只有一些老项目中,或者是极其特殊的情况中,才会使用
主要还是为了面试
什么是闭包
概念: 是js中,函数的一种高级应用方式
作用: 调用函数中局部作用域变量,在函数之外,可以直接使用
正常情况下,只能使用 return 返回 局部作用域变量的数值
要想调用使用 int 就必须要使用 闭包
return 只能返回一个数值,
使用闭包的形式,可以返回调用,多个数值数据
闭包的执行条件
要使用执行闭包,必须要有3个条件,缺一不可
1, 在函数A中,直接返回一个函数B
即函数A的返回值是另一个函数B
2, 函数B中,调用使用函数A中的局部作用域变量
3, 函数A 外部 有一个变量 存储接收 函数B
// function fun(){
// // 定义在函数内部的局部作用域变量
// var int1 = 100;
// // 通过 return 返回的 int 中存储的数值100
// // 但是这个变量 int 仍然不能被使用
// return int1;
// }
// fun();
// 在函数外部,无法直接使用局部作用域变量
// console.log(int1);
// 闭包的写法
// 定义一个函数A
function funA(){
// 函数A中有一个局部作用域变量
var int21 = 100;
var int22 = 200;
var int23 = 300;
// 函数A,返回值,是另一个函数B
// 函数A的执行结果,返回值就是函数B
return function funB(){
// 函数B中,调用执行了函数A中的变量 int3
var int31 = int21;
var int32 = int22;
var int33 = int23;
console.log(int31,int32,int33);
}
}
// 有一个外部的变量,来存储函数B
// f 中 存储的是 funA 函数的执行结果,也就是 函数B
// funA() 的执行结果是 function funB(){}
// 等于 是 一个匿名函数 const f = function funB(){}
// f 中 存储的是 funB() 的 内存地址
// f() 就是 调用的 funB() 这个函数
const f = funA();
// 此时 执行 f() , 就是通过存储的地址, 执行函数B()
f(); // 100 200 300
// 此时,int2变量,在函数外部仍然无法直接使用
// 但是int2的数值数据,可以在函数外部直接使用
console.log(int21); // 报错
函数的执行空间
二.重新了解函数
<script>
重新了解函数
1, 复习一下函数的执行步骤
(1), 定义函数
1, 在内存中开辟一个空间,准备来存储函数
2, 将程序内容,以字符串形式,存储在,内存空间中
3, 将存储空间的内存地址,赋值给变量或者函数名称存储
(2), 调用执行函数
1, 按照变量或者函数名称中,存储的内存地址,找到存储空间
2, 给函数形参,赋值实参
3, 对函数程序进行预解析
4, 将存储的程序,调用并且执行
重新认识函数的调用执行过程
在函数的执行过程中,在内存中,会再独立开辟一个执行空间,用于执行函数的程序内容
这个独立的执行空间,在函数的存储空间中定义
// 在内存空间中,开辟一个 存储空间 ,来 存储函数的程序内容
// 存储时,函数的程序,以字符串形式,存储在存储空间中,没有被执行
function fun(){
let int = 100;
}
// 执行调用函数
// 在 存储空间 中 开辟一个 执行空间 ,来执行函数程序
// let int = 100; 声明定义的变量 int 只存在于 执行空间中
fun();
// 执行函数完毕,执行空间会被销毁,
// 那么 只 存在于 执行空间中的 变量 int 也会被销毁
// 要想 调用 函数内部 声明的变量的数据
// 就要确保 执行空间不被销毁
// 如何确保执行空间不被销毁
// 1,在函数内容部,返回一个引用类型(数组,对象,函数,以函数为主)
// 2,在函数的外部,有变量来引用这个函数
// 3,此时,函数的执行空间就不会被销毁
// 定义一个函数,返回一个引用数据类型,只要是数组,对象,函数就可以
function fun2(){
let int = 100;
return function (){
console.log(int);
}
};
// f 中存储的是, fun2() 这个函数的执行结果
// 也就是 存储的是 return 的 引用数据类型 的 地址
// 此时,如果 执行空间 被 销毁,f中存储的 引用数据类型的地址,也就没有意义
// 因此,函数 fun2 中的 执行空间会被保存,不会被销毁
// 只要 f 存在 , fun2 的执行空间就会一直被保存,不被销毁
let f = fun2();
f(); // 100
// 重新给 f 赋值一个新的内容,不再存储 fun2() 返回的引用数据类型的内存地址
// 此时, fun2 的执行空间也就被销毁了
f = 123;
</script>