从闭包到柯里化:JS 函数进阶实战指南(超易懂版~)
一、闭包:JS 函数的 “记忆魔法”
(一)闭包是什么?
闭包就是一个函数可以访问并记住外层函数作用域的变量~简单来说,就是 “函数嵌套函数,内层函数引用外层变量”。比如:
function outer() {
let count = 0;
function inner() {
count++; // 记住了外层的count变量
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
就像内层函数带了一个 “小书包”,把外层的变量都装进去啦~
(二)闭包的核心原理
- 词法作用域嵌套:函数定义时确定作用域链,内层函数可以访问外层函数的变量
- 引用保持:外层函数执行完后,变量不会被销毁,因为内层函数还在引用它
- 闭包三要素:函数嵌套 + 内层引用外层变量 + 外层返回内层函数
(三)闭包的实用场景
- 封装私有变量:像银行账户,外部只能通过特定方法操作余额
- 防抖节流:表单搜索时,等用户输入完再触发查询(超实用的性能优化技巧哦~)
- 函数柯里化:后面会重点讲!先记住它需要闭包来收集参数
二、函数拆解:JS 函数的十八般武艺
(一)函数是一等公民
在 JS 里,函数和数字、字符串一样,可以:
- 赋值给变量:
const fn = function() {}
- 作为参数传递:
arr.map(function(item) {})
- 作为返回值:
function outer() { return function() {} }
(二)函数的多样形态
-
匿名函数 & 立即执行函数(IIFE)
匿名函数没有名字,常用来做回调;IIFE 定义后立即执行,比如:(function() { console.log("我是立即执行的~"); })();
-
箭头函数 vs 传统函数
箭头函数更简洁,而且this
指向定义时的作用域(再也不用担心this
乱跑啦~):const arrowFn = (a, b) => a + b; // 一行代码直接返回
-
递归函数
自己调用自己,适合解决分治问题,比如计算阶乘:function factorial(n) { return n === 0 ? 1 : n * factorial(n - 1); }
三、柯里化:让函数参数 “慢慢来”
(一)柯里化是什么?
把一个多参数函数变成多个单参数函数的嵌套~比如:
// 普通函数
add(1, 2, 3); // 直接传3个参数
// 柯里化后
const addCurry = curry(add);
addCurry(1)(2)(3); // 分3次传参,最后计算结果
就像收集龙珠,每次收集一个参数,凑够了就召唤神龙(执行函数)!
(二)手写一个万能 curry 函数
核心思路:
-
记住原函数需要的参数个数(
fn.length
) -
每次调用收集参数,直到参数够了就执行原函数
-
用闭包保存已收集的参数
function curry(fn) {
// 收集参数的“小仓库”
const argsList = [];
return function judge(...newArgs) {
argsList.push(...newArgs);
// 凑够参数就执行
if (argsList.length >= fn.length) {
return fn(...argsList);
}
// 不够的话继续返回收集函数
return judge;
};
}
// 测试一下
function add(a, b, c) {
return a + b + c;
}
const addCurry = curry(add);
console.log(addCurry(1)(2)(3)); // 6,成功啦!
(三)柯里化的优势
- 参数复用:比如固定请求的基础参数,后面只传变化的部分
- 函数拆分:把复杂函数拆成简单的单参数函数,更易维护
- 逻辑清晰:每次只关心一个参数,代码可读性 UP!
四、避坑指南:闭包与柯里化的正确打开方式
(一)闭包的内存问题
- 不要滥用闭包,避免大量变量无法释放
- 不用时及时释放引用:
closure = null;
(二)柯里化的参数匹配
- 注意原函数的参数个数(
fn.length
)要准确 - 支持传多个参数:比如
addCurry(1, 2)(3)
也是可以的哦~
(三)代码规范建议
- 复杂逻辑加注释,比如 curry 函数的参数收集过程
- 保持函数单一职责,柯里化函数只负责参数收集
总结:从基础到进阶的函数之旅
闭包就像函数的 “记忆魔法”,让内层函数能记住外层的变量;
柯里化则是参数的 “收集器”,让函数调用更灵活~
掌握这些进阶技巧,写代码时就能像搭积木一样轻松组合功能啦!
下次遇到复杂函数场景,记得试试闭包和柯里化哦,说不定会有惊喜~🤓