一、认识函数的过程
1. 定义
- 在堆内存中开辟一段内存空间(XF001)
- 把函数体的内容,完全百分百的照抄一份,存放在内存空间中(XF001)
- 把内存空间的地址(XF001) 赋值给函数名
2. 调用
- 根据函数名内存储的地址 (XF001) ,去堆内存中找到对应函数
- 会去运行内存中, 开辟一段新的内存, 用于运行函数 (函数作用域)
- 形参赋值---预解析---函数代码全部执行结束
- 函数执行完毕之后, 这段内存空间会被销毁
function fn() {
let a = 100
console.log(a)
}
fn()
二、认识不会被销毁的内容空间
1. 函数向外部返回了一个引用数据类型(返回的是引用数据类型的地址)
2. 外部有一个变量接受这个返回值 (外部变量中有变量,拿到这个引用地址)
3. 为了我们后续能够正常使用, JS 不会把这个函数的运行空间销毁
function fn () {
let obj = {
a: 1,
b: 2
}
return obj
}
let o1 = fn()
console.log(o1)
三、闭包
- 重点:看清楚我们调用的是那个函数
1、构成条件
- 需要一个不会被销毁的函数执行空间
- 需要直接或间接的返回一个函数
- 内部函数使用外部函数的私有变量
2、闭包的好处
- 延长变量的作用域(使用时间)
- 函数外部可以使用函数内部的变量
3、闭包的弊端
- 因为闭包的存在就一定代表一个函数执行空间不会被销毁, 如果大量使用闭包, 会导致内存空间占据严重
4、代码实现
function outer() {
let a = 100
let str = 'QF001'
let obj = {
a: 1,
b: 2
}
function inner() {
return a;
}
return inner;
}
// 1. 调用outer到内层函数inner, 存到了变量res中
let res = outer();
/**
* 2. 调用res 也就是调用内层函数inner, 调用完成之后,因为函数内部return str,
* 得到了一串字符串
* 将这个字符串存储到了newStr这个变量中
*/
let newStr = res();
// 3. 打印newStr 得了outer函数中str变量
console.log(newStr); // 100