深入理解闭包、偏函数、函数柯里化、高阶函数、IIFE

2024-06-18 00:21:55

浏览:72

评论: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 () {
    //...
});