深入理解闭包、偏函数、函数柯里化、高阶函数、IIFE
2024-06-18 00:21:55
浏览:71
评论:0
闭包
什么是闭包
闭包需要满足三个条件:
- 内部函数嵌套在外部函数(父函数)里面。
- 内部函数可以访问其外部函数(父函数)的变量,即使外部函数(父函数)已经执行结束。
- 闭包在内部函数在外部函数(父函数)作用域之外被引用时“生效”,但实际上闭包在内部函数定义时就已经形成,只是在被引用时其特性表现得更为明显。
// 函数嵌套
function domain() {
let str = "https://tool.vscing.com"
// 定义闭包函数
return function vscing() {
// 访问外部作用域
console.log(str);
}
}
// 闭包函数 “生效”
var domainStr = domain();
domainStr(); // https://tool.vscing.com
闭包特性
- 可以避免使用全局变量,防止全局变量污染。
- 内部函数的执行需要依赖外部函数(父函数)中的变量,外部函数(父函数)作用域中的变量会常驻在内存中,使得Javascript的垃圾回收机制不会收回外部函数(父函数)所占用的资源。
function outerFn(){
var i = 0;
function innerFn(){
i++;
console.log(i);
}
return innerFn;
}
var inner = outerFn();
inner(); // 1
inner(); // 2
inner(); // 3
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
避免内存泄露
- 事件监听器、setTimeout、setInterval等要使用完后进行移除。
- 全局变量的生命周期与整个应用程序相同,容易造成意外的内存泄漏。尽量使用局部变量。
- 使用WeakMap或WeakSet来存储对象,这样当对象没有其他强引用时,垃圾回收器可以自动回收它们。
应用场景
- 防抖、节流函数
- 偏函数、函数柯里化
偏函数
偏函数是一个接受部分参数的函数,返回一个新的函数来处理剩余的参数。这种技术可以用来减少函数调用时需要指定的参数数量。
// 定义一个求两个数的和的函数
function add(a, b) {
return a + b;
}
// 创建一个偏函数,它接受一个参数a
function partialAdd(a) {
// 返回一个新函数,这个函数接受另一个参数b并调用原始的add函数
return function(b) {
return add(a, b);
};
}
// 使用偏函数
const addFive = partialAdd(5); // 创建一个用来添加5的偏函数
console.log(addFive(3)); // 输出: 8
console.log(addFive(10)); // 输出: 15
函数柯里化
柯里化是将接受多个参数的函数转换为接受一个单一参数(最初函数的第一个参数)的函数,并返回接受余下参数并返回结果的新函数的技术。这种技术常用于创建可组合的、高阶的函数。
function curry(fn) {
return function(a) {
return function(b) {
return fn.call(this, a, b);
};
};
}
// 使用currying技术的加法函数
function add(a, b) {
return a + b;
}
var addCurried = curry(add);
var increment = addCurried(1);
console.log(increment(2)); // 输出: 3
高阶函数
高阶函数是指接收函数作为参数或者将函数作为输出结果的函数。在JavaScript中,高阶函数可以用来实现高阶函数式编程的特性,例如:map、reduce、filter、sort等。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
IIFE
立即执行函数就是声明一个匿名函数,并马上调用这个匿名函数。创建一个独立的作用域,这个作用域里面的变量,外面访问不到(即避免"变量污染")。
// UMD 打包 本质就是把 AMD 和 CommonJS 结合在一起
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory;
} else {
root.MYMODULE = factory();
}
})(this, function () {
//...
});