放肆青春的博客
首页
前端
算法
网络
面试
技术
后端
运维
杂项
数据库
工具
网址
电脑
个人
文章
  • 分类
  • 标签
  • 归档
github (opens new window)
gitee (opens new window)

放肆青春

一个前端菜鸟的技术成长之路
首页
前端
算法
网络
面试
技术
后端
运维
杂项
数据库
工具
网址
电脑
个人
文章
  • 分类
  • 标签
  • 归档
github (opens new window)
gitee (opens new window)
  • 前端

    • 前端 概览
    • 前端汇总

    • front 博文

    • front 项目总结

    • front 高级

    • front tools

  • vue

    • vue 概览
    • vue 汇总

    • vue 博文

    • vue 项目总结

    • vue 高级

  • html

    • html 概览
    • html 汇总

    • html 博文

  • css

    • css 概览
    • css 汇总

    • css 博文

    • sass

    • less

  • js

    • javascript 概览
    • JS 汇总

    • ES6

    • JS 博文

      • js 基础语法
      • js 数据类型
      • js 字符串
      • js 数组
      • js 对象
      • js 变量
      • js 函数
      • js 事件
      • js 循环
      • js 浅拷贝和深拷贝
      • js 动画
      • js DOM
      • js 防抖节流
      • js 原型及原型链
      • js this
      • js 作用域
      • js 继承
      • js 闭包
        • js 闭包
          • 闭包关联知识点
          • 创建闭包函数的两种情况
          • 闭包优点
          • 闭包缺点
          • 使用闭包注意点
          • 闭包一定会造成内存泄漏吗
          • 什么时候闭包会清除?
      • js 内存
      • js垃圾回收
    • JS 工具

  • node

    • node 概览
    • node 汇总

    • node 框架

    • node 博文

  • react

    • react 概览
    • react 汇总

    • react 博文

    • react 高级

  • 微信小程序

    • 微信小程序 概览
    • 微信小程序总结
    • 微信小程序文章
    • 微信小程序 博文

    • 微信小程序 高级

  • 微信公众号

    • 微信公众号 概览
    • 微信公众号总结
    • 微信公众号文章
  • 多端开发

    • 多端开发
    • dsbridge 概览
    • jsbridge 概览
    • webview
    • uniapp

      • uniapp 概览
    • taro

      • taro 概览
    • flutter

      • flutter 概览
      • flutter 环境搭建
    • electron

      • electron 概览
  • front
放肆青春
2021-03-22

js 闭包

# js 闭包

闭包是指有权访问另一个函数作用域中的变量的函数

闭包是函数式编程

闭包的三个特性:

  1. 函数嵌套函数

  2. 函数内部可以引用函数外部的参数和变量

  3. 参数和变量不会被垃圾回收机制回收

# 闭包关联知识点

自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量,其实就是另外一个函数作用域中的变量。

闭包中的变量并不保存中栈内存中,而是保存在堆内存中

# 创建闭包函数的两种情况

  1. 函数作为返回值

  2. 函数作为参数传递

# 闭包优点

  1. 避免全局变量的污染

  2. 模块化代码:使用自执行的匿名函数来模拟块级作用域

es6 没出来之前,用 var 定义变量存在变量提升问题

for (var i = 0; i < 10; i++) {
  console.info(i);
}
alert(i)(
  // 变量提升,弹出10

  //为了避免i的提升可以这样做
  function() {
    for (var i = 0; i < 10; i++) {
      console.info(i);
    }
  }
)();
alert(i); // underfined   因为i随着闭包函数的退出,执行环境销毁,变量回收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)

# 闭包缺点

  1. 参数和变量常驻内存,增加内存使用量。

  2. 使用不当会很容易造成内存泄露

# 使用闭包注意点

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
function showId() {
  var el = document.getElementById("app");
  el.onclick = function() {
    aler(el.id); // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
  };
}

// 改成下面
function showId() {
  var el = document.getElementById("app");
  var id = el.id;
  el.onclick = function() {
    aler(id); // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
  };
  el = null; // 主动释放el
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  2. this 指向问题

var object = {
     name: ''object",
     getName: function() {
        return function() {
             console.info(this.name)
        }
    }
}
object.getName()()    // underfined
// 因为里面的闭包函数是在window作用域下执行的,也就是说,this指向windows
1
2
3
4
5
6
7
8
9
10

# 闭包一定会造成内存泄漏吗

准确的说是在 IE9 之前才会有闭包变量内存泄漏的问题。

因为 IE9 之前采用的垃圾回收算法不是现在使用的清除标记算法,而是引用计数算法。

引用计数算法在处理 COM 对象(组件对象模型)会有循环引用的问题,而循环引用才是导致内存泄漏的元凶。

在早期的 V8 中,由于闭包引用的变量被挂载了全局的大对象 windows 中,所以这一变量由老生代区采用标记清除算法进行回收。频繁的垃圾回收会生成大量的内存碎片,所以也会导致内存泄漏问题。

为了解决这一问题,以及频繁的垃圾回收导致的全停顿问题(垃圾回收在主线程执行),后来 v8 又采用了标记清除整理算法,以及增量回收、并行回收、并发回收等垃圾回收技术,所以在新一代浏览器中,使用闭包几乎不会出现内存泄漏问题。

# 什么时候闭包会清除?

将闭包的函数置为 null

更新时间: 2/10/2022, 7:21:32 PM
js 继承
js 内存

← js 继承 js 内存→

最近更新
01
前端权限管理
02-24
02
vue2指令
02-24
03
vue2 hook
02-24
更多文章>
Theme by Vdoing | Copyright © 2019-2022 放肆青春
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式