闭包与柯里化
约 1045 字大约 3 分钟
2025-08-06
闭包
闭包的概念: 一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
闭包形成的原理: 作用域链,当前作用域可以访问上级作用域中的变量
闭包解决的问题: 能够让函数作用域中的变量在函数执行结束之后不被销毁,同时也能在函数外部可以访问函数内部的局部变量。
闭包带来的问题: 由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。
闭包的应用: 能够模仿块级作用域,能够实现柯里化,在构造函数中定义特权方法、Vue中数据响应式Observer中使用闭包等。 ...
块级作用域是指在JavaScript中,由一对花括号{}包裹的代码区域,例如循环体、条件语句体等。在块级作用域内声明的变量,其作用范围仅限于该块内部,外部无法访问这些变量12。ES6引入了let
和const
关键字,使得JavaScript支持块级作用域,这有助于减少全局变量的使用,提高代码的模块化和可维护性12。
简单理解:闭包 = 内层函数 + 外层函数的变量
闭包是一种比较特殊的函数,使用闭包能够访问函数作用域中的变量。从代码形式上看闭包是一个做为返回值的函数,如下代码所示:
<body>
<script>
//1. 闭包 : 内层函数 + 外层函数变量
//简单的写法
function outer() {
const a = 1
function f() {
console.log(a)
}
f()
}
outer()//此时就产生了闭包
// 常见的闭包的形式 外部可以访问使用 函数内部的变量
function outer() {
let a = 100
function fn() {
console.log(a)
}
return fn
}
//调用outer()函数,返回fn函数,即
//outer() === fn === function fn() {}
//所以 const fun = function fn() { } //用fn变量来接收,得到fn函数
const fun = outer()
fun() //调用函数,打印出a的值100,相当于在外部访问了变量a的值
//2. 闭包的应用: 实现数据的私有。统计函数的调用次数
let count = 1
function fn() {
count++
console.log(`函数被调用${count}次`)
}
//但是这样的写法,count变量在外部,很容易被别人修改
//闭包的写法 统计函数的调用次数
function outer() {
let count = 1
function fn() {
count++
console.log(`函数被调用${count}次`)
}
return fn
}
const re = outer()
//相当于:
// const re = function fn() {
// count++
// console.log(`函数被调用${count}次`)
// }
re()
re()
// const fn = function() { } 函数表达式
// 4. 闭包存在的问题: 可能会造成内存泄漏
</script>
</body>
总结:
1.怎么理解闭包?
- 闭包 = 内层函数 + 外层函数的变量
2.闭包的作用?
- 封闭数据,实现数据私有,外部也可以访问函数内部的变量
- 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来
3.闭包可能引起的问题?
- 内存泄漏
柯里化
是一种将使用多个参数的函数转换成一系列使用一个参数的函数的技术。通过柯里化,可以将一个多参数的函数转换成一系列单参数的函数,每个函数返回下一个待调用的函数,直到最后一步调用时才执行原函数。柯里化常用于减少参数错误和提高代码的可读性和重用性.
柯里化是一个预处理思想,使用闭包形成一个不被释放的上下文,把一些信息存储起来,以后基于作用域链,访问到事先存储的信息,然后进行先关处理,我们把这种模式称为柯里化函数。
//预处理变量n,子作用域能够访问到该变量
function fn(n=10){
return function(...args){
return args.reduce((value,item) => value+item,n);
}
}
let sum=fn();
console.log(sum(1,2,3));