javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > js闭包应用场景

js闭包的6种应用场景总结

作者:xxx17

如果一个函数访问了此函数的父级及父级以上的作用域变量,那么这个函数就是一个闭包,本文将给大家分享js闭包的6种应用场景,文中有详细的代码示例,需要的朋友可以参考下

什么是闭包?

闭包的基本定义

如果一个函数访问了此函数的父级及父级以上的作用域变量,那么这个函数就是一个闭包。闭包会创建一个包含外部函数作用域变量的环境,并将其保存在内存中,这意味着,即使外部函数已经执行完毕,闭包仍然可以访问和使用外部函数的变量。

//闭包实例代码
function fn1() {
  let a = 1;
  function fn2() {
    a++;
    console.log(a);
  }
  return fn2;
}
const fn2 = fn1();
//闭包函数执行完后外部作用域变量仍然存在,并保持状态
fn2() //2
fn2() //3

闭包的优缺点及特性

闭包的应用场景

自执行函数

let say = (function(){
  let val = 'hello world';
  function say(){
    console.log(val);
  }
  return say;
})()

节流防抖

// 节流函数封装
function throttle(func, delay) {
  let timer = null;
  return function () {
    if (!timer) {
      timer = setTimeout(() => {
        func.apply(this, arguments);
        timer = null;
      }, delay);
    }
  };
}
// 防抖函数封装
function debounce(func, delay) {
  let timer = null;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  };
}

函数柯里化

//柯里化前
function add(a, b, c) {
  return a + b + c;
}
console.log(add(1, 2, 3)); //6
//柯里化后
function addCurried1(a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
}
//箭头函数简写
const addCurried2 = (a) => (b) => (c) => a + b + c;
console.log(addCurried1(1)(2)(3)); //6
console.log(addCurried2(1)(2)(3)); //6

链式调用

function calculator() {
  let result = 0;
  function add(num) {
    result += num;
    return this;
  }
  function subtract(num) {
    result -= num;
    return this;
  }
  function multiply(num) {
    result *= num;
    return this;
  }
  function divide(num) {
    result /= num;
    return this;
  }
  function getResult() {
    return result;
  }
  function clear() {
    result = 0;
    return this;
  }
  return {
    add,
    subtract,
    multiply,
    divide,
    getResult,
    clear,
  };
}
const calc = calculator();
const result = calc.add(5).subtract(2).divide(3).multiply(6).getResult();
console.log(result); // 输出:6

迭代器

function createIterator(arr) {
  let index = 0;
  return {
    next: function() {
      if (index < arr.length) {
        return {
          value: arr[index++],
          done: false
        };
      } else {
        return {
          done: true
        };
      }
    }
  };
}
const myIterator = createIterator([1, 2, 3]);
console.log(myIterator.next()); // { value: 1, done: false }
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next()); // { value: 3, done: false }
console.log(myIterator.next()); // { done: true }

发布-订阅模式

function createPubSub() {
  // 存储事件及其对应的订阅者
  const subscribers = {};
  // 订阅事件
  function subscribe(event, callback) {
    // 如果事件不存在,则创建一个新的空数组
    if (!subscribers[event]) {
      subscribers[event] = [];
    }
    // 将回调函数添加到订阅者数组中
    subscribers[event].push(callback);
  }
  // 发布事件
  function publish(event, data) {
    // 如果事件不存在,则直接返回
    if (!subscribers[event]) {
      return;
    }
    // 遍历订阅者数组,调用每个订阅者的回调函数
    subscribers[event].forEach((callback) => {
      callback(data);
    });
  }
  // 返回订阅和发布函数
  return {
    subscribe,
    publish,
  };
}
// 使用示例
const pubSub = createPubSub();
// 订阅事件
pubSub.subscribe("event1", (data) => {
  console.log("订阅者1收到事件1的数据:", data);
});
pubSub.subscribe("event2", (data) => {
  console.log("订阅者2收到事件2的数据:", data);
});
// 发布事件
pubSub.publish("event1", "Hello");
// 输出: 订阅者1收到事件1的数据: Hello
pubSub.publish("event2", "World");
// 输出: 订阅者2收到事件2的数据: World

闭包造成的内存泄漏怎么解决呢?

闭包中的内存泄漏指的是在闭包函数中,由于对外部变量的引用而导致这些变量无法被垃圾回收机制释放的情况。当一个函数内部定义了一个闭包,并且这个闭包引用了外部变量时,如果这个闭包被其他地方持有,就会导致外部变量无法被正常释放,从而造成内存泄漏。
解决闭包中的内存泄漏问题通常需要注意解除外部变量和闭包函数的引用,以及解绑函数本身的引用,使得闭包中引用的外部变量和闭包函数能够被垃圾回收机制释放。

function createClosure() {
  let value = 'Hello';
  // 闭包函数
  var closure = function() {
    console.log(value);
  };
  // 解绑定闭包函数,并释放资源
  var releaseClosure = function() {
    value = null; // 解除外部变量的引用
    closure = null; // 解除闭包函数的引用
    releaseClosure = null; // 解除解绑函数的引用
  };
  // 返回闭包函数和解绑函数
  return {
    closure,
    releaseClosure
  };
}
// 创建闭包
var closureObj = createClosure();
// 调用闭包函数
closureObj.closure(); // 输出:Hello
// 解绑闭包并释放资源
closureObj.releaseClosure();
// 尝试调用闭包函数,此时已解绑,不再引用外部变量
closureObj.closure(); // 输出:null

以上就是js闭包的6种应用场景总结的详细内容,更多关于js闭包应用场景的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文