首页 > 其他分享 >JS 垃圾回收与闭包

JS 垃圾回收与闭包

时间:2024-12-11 18:36:31浏览次数:12  
标签:闭包 function return args JS 垃圾 fn 引用

垃圾回收

标记清除

当变量进入环境时,将其标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。垃圾回收器会销毁那些带标记的值,并回收它们所占用的内存空间。

function test() {
  var a = 1; // 函数调用时 被标记 进入上下文
}
test(); // 函数执行完毕,a的标记去掉,被回收

引用计数

当声明一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。当垃圾回收器下次再运行时,它就会释放那些引用次数为0的值所占用的内存。

function test() {
  var a = {}; // a的引用次数为0,被回收
  var b = a; // a的引用次数加1,为1
  var c = a; // a的引用次数再加1,为2
  a = 1; // a的引用次数减1,为1
  b = 1; // a的引用次数减1,为0,可以被回收了
  c = 1; // a的引用次数减1,为0,可以被回收了
}

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。闭包使得函数可以继续访问定义时的词法作用域。

闭包的另一个用处,是封装私有变量。

function createCounter() {
  let count = 0;
  return {
    increment: function () {
      count++;
    },
    getCount: function () {
      return count;
    },
  };
}

const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 1

闭包的缺点:

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
  3. 闭包的缺点就是常驻内存,会增大内存使用量,并且使用不当很容易造成内存泄露。

闭包的用途

  1. 创建私有变量
    function createCounter() {
      let count = 0;
      return {
        increment: function () {
          count++;
        },
        getCount: function () {
          return count;
        },
      };
    }
    
  2. 模拟块级作用域
    (function () {
      for (var i = 0; i < 10; i++) {
        console.log(i);
      }
    })();
    
  3. 实现柯里化
    function add(a, b, c) {
      return a + b + c;
    }
    
    function curry(fn) {
      return function curried(...args) {
        if (args.length >= fn.length) {
          return fn.apply(this, args);
        } else {
          return function (...args2) {
            return curried.apply(this, args.concat(args2));
          };
        }
      };
    }
    
    const curriedAdd = curry(add);
    console.log(curriedAdd(1)(2)(3)); // 6
    
  4. 实现函数节流和防抖
    function throttle(fn, delay) {
      let timer = null;
      return function (...args) {
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(this, args);
            timer = null;
          }, delay);
        }
      };
    }
    
    function debounce(fn, delay) {
      let timer = null;
      return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          fn.apply(this, args);
        }, delay);
      };
    }
    
  5. 实现单例模式
    function Singleton(fn) {
      let instance = null;
      return function (...args) {
        if (!instance) {
          instance = new (fn.bind(this, ...args))();
        }
        return instance;
      };
    }
    
    function User(name) {
      this.name = name;
    }
    
    const createUser = Singleton(User);
    const user1 = createUser('Alice');
    const user2 = createUser('Bob');
    console.log(user1 === user2); // true
    
  6. 实现模块化开发
    const module = (function () {
      let privateVar = 0;
      function privateFunc() {
        console.log('privateFunc');
      }
      return {
        publicFunc: function () {
          console.log('publicFunc');
        },
      };
    })();
    module.publicFunc(); // publicFunc
    module.privateFunc(); // TypeError: module.privateFunc is not a function
    

标签:闭包,function,return,args,JS,垃圾,fn,引用
From: https://www.cnblogs.com/zhuping580/p/18600408

相关文章

  • Java 中的 CMS 和 G1 垃圾收集器如何维持并发的正确性?
    Java中的CMS和G1垃圾收集器如何维持并发的正确性?CMS(ConcurrentMark-Sweep)和G1(Garbage-First)垃圾收集器是两种低延迟的垃圾回收器,它们通过并发阶段与应用线程(Mutator)同时运行,以减少暂停时间。为了维持并发垃圾回收的正确性,二者采取了不同的技术和策略。1.CMS垃圾收集器......
  • 10位时间戳、13位时间戳以及17位时间戳在JS中的格式转换
    目录目录目录一、介绍1、10位时间戳2、13位时间戳3、17位时间戳二、13位时间戳的转换1、获取当前时间的13位时间戳2、转换成标准日期3、转换成格式化日期三、10位时间戳的转换1、获取当前时间的10位时间戳2、转换成标准日期3、转换成格式化日期四、17位时间戳的转换一、介绍1、......
  • Java 的 CMS 垃圾回收器和 G1 垃圾回收器在记忆集的维护上有什么不同?
    Java的CMS垃圾回收器和G1垃圾回收器在记忆集的维护上的不同记忆集(RememberedSet,RSet)是垃圾回收器用来跟踪跨代引用的重要结构,它记录老年代对象对新生代对象的引用。CMS和G1垃圾回收器在记忆集的维护方式和粒度上有显著差异。1.CMS垃圾回收器的记忆集维护1.1粒度......
  • 为什么 G1 垃圾收集器不维护年轻代到老年代的记忆集?
    为什么G1垃圾收集器不维护年轻代到老年代的记忆集?在G1垃圾收集器中,不维护年轻代到老年代的记忆集(RememberedSet,RSet)是因为其设计特点和优化策略使得这种记忆集的维护既不必要也无意义。1.G1的设计特点1.1分区化设计G1将堆划分为多个大小固定的分区(Region),每个分区......
  • 浅谈 Java 垃圾回收机制
    浅谈Java垃圾回收机制文章目录浅谈Java垃圾回收机制一、引言二、垃圾回收算法要解决的问题(一)内存泄漏问题(二)悬空指针问题三、常见的垃圾回收算法(一)标记-清除算法(Mark-SweepAlgorithm)(二)复制算法(CopyingAlgorithm)(三)标记-整理算法(Mark-CompactAlgorithm)(四)分代......
  • FineReport其他js记录
    1.js修改日期组件背景色边框setTimeout(function(){​varcolor="#092347";​varfontColor="white";​//日期控件​$$(".report-main-parameter-container-controller-datetime").css({"background":color});//设置背景$$(".report-main-par......
  • 为什么 Java 中某些新生代和老年代的垃圾收集器不能组合使用?
    为什么Java中某些新生代和老年代的垃圾收集器不能组合使用?在JVM中,新生代和老年代的垃圾收集器是分工协作的。然而,并非所有的新生代和老年代垃圾收集器都能任意组合使用,这是由于它们的设计目标、算法特性和交互方式不兼容所导致的。例如,新生代的ParNew和老年代的ParallelO......
  • js逆向-2-跟栈
    wy云js加密逆向登录的时候会加密我们输入的电话号码,我们需要得到这个Params的加密方法首先点击登录之后抓取数据包,点击第一个,并打上断点然后点击发送验证码就会断住这里的arguments里面就有我们想要的值,然后继续跟栈这里显示a的值通过o[0]获取的,然后继续跟进栈显示a=i[......
  • 利用husky.js git hooks实现图片自动压缩功能
    场景在一般的网页开发过程中,往往我们都要下载较多的切图,而这些切图未必都做了压缩,即使做了压缩,效果未必能达到理想效果。要解决这种图片压缩问题,途径有很多1.手动将图片丢到xx站点,压缩好之后再放进项目2.让UI给已经压缩好的图这些方式都得靠人工操作,人工操作往往存在一些不......
  • JVM 垃圾回收时产生的 concurrent mode failure 的原因是什么?
    JVM垃圾回收时产生的concurrentmodefailure的原因是什么?在JVM中,concurrentmodefailure是垃圾回收器(通常是CMS,即ConcurrentMark-SweepGC)在执行并发垃圾回收时,因老年代空间不足导致的失败。这种失败会迫使JVM采用Stop-The-World(STW)的方式,执行一次单线程的FullG......