欢迎光临散文网 会员登陆 & 注册

千锋教育JavaScript全套视频教程(10天学会Js,前端javascrip

2023-07-21 09:18 作者:名咩咩咩咩  | 我要投稿

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之就是可以让内部函数访问到外部函数的作用,闭包会随着函数的创建而被同时创建。

 我们来创建一个简单的闭包。


     function fn(){

      let i = 0;

      return function(){

        i++;

        return i;

      }

    }

    let isSum = fn();

    console.log(isSum());

    console.log(isSum());

    console.log(isSum());

    console.log(isSum());



 我们可以看到我们访问的是内部函数,但是却用到了外部函数中的变量,而且我们发现我们每一次的调用实际过程中外部变量并没有从新定义而是像全局变量一样做到了常驻。为什么会这样的效果呢?这就运用到了闭包的两个基本原理:垃圾回收机制、作用域链。


垃圾回收机制、作用域链


垃圾回收机制可分为两种方式分别是:引用计数法、标记清除法。

引用计数法:这种方式常常会引起内存泄漏,低版本的IE使用这种方式。机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时,则说明没有办法再访问这个值了,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。引用计数方法可能导致循环引用,类似死锁,导致内存泄露。


标记清除:JavaScript中常用的清除机制


(1)当变量进入执行环境时(函数中声明变量),就标记这个变量为“进入环境”,当变量离开环境时(函数执行结束),则将其标记为“离开环境”,离开环境之后还有的变量则是需要被删除的变量。


(2)垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。


(3)去掉环境中的变量以及被环境中变量引用的变量的标记。


(4)之后再被加上标记的变量即是需要回收的变量(因为环境中的变量已经无法访问到这些变量)


(5)最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。



作用域链

各个作用域的嵌套关系组成一条作用域链。例子中 内部函数的作用域链式 本身 -> fn -> 全局, fn函数保存在作用域链式 fn -> 全局

作用域链主要是进行标识符(变量和函数)的查询,标识符解析就是沿着作用域链一级一级的搜索标识符的过程,而作用域链就是保证对变量和函数的有序访问。


闭包的优点


可以减少全局变量的定义,避免全局变量的污染

能够读取函数内部的变量

在内存中维护一个变量,可以用做缓存

闭包的缺点


造成内存泄露 :闭包会使函数中的变量一直保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法——使用完变量后,手动将它赋值为null;

闭包可能在父函数外部,改变父函数内部变量的值。

千锋教育JavaScript全套视频教程(10天学会Js,前端javascrip的评论 (共 条)

分享到微博请遵守国家法律