闭包的作用与原理

247 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

核心描述

  • 什么是闭包
    • MDN描述:一个函数和对其周围状态(Iexical environment, 词法环境)的引用捆绑在一起(或者函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
    • JavaScript 高级程序设计中的描述:闭包指的是哪些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。
    • 简单理解:闭包就是能够读取其他函数内部变量的函数,即定义在一个函数内部的函数。本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
    • 还可以理解:闭包是指有权访问另一个函数作用域中的变量的函数。
  • 闭包的作用
    • 在 JS 中模拟私有方法,即只能被同一个类中的其他方法所调用。
    • 在循环中创建闭包,比如批量给 DOM 元素增加点击事件,尤其是在 ES6 出来之前,没有 let 语法时。
    • 外部读取局部变量,让函数外部的能够获取到函数内部定义的变量的值。
    • 让函数的内部变量始终保持在内存中。
  • 闭包存在的问题
    • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包。解决方法是可以在退出函数之前或是不再使用函数内部变量时,将局部变量删除或置为 null ,便于浏览器内部回收。
    • 对处理速度具有负面影响。闭包的层级决定了引用的外部变量在查找时经过的作用域链长度
    • 可能获取到意外的值

知识拓展

  • 闭包在程序设计中的作用
    • 闭包并不是 JavaScript 独有的特性
    • 闭包有数学概念中的理解
    • 闭包有函数式编程概念中的理解
    • 像 Python \ C++ \ Scheme 等编程语言中都有类似闭包的概念
  • 闭包在项目中的应用
    • 模块封装,在各模块规范出现之前,以及 ES6 的 Class 语法出现之前,常用闭包实现私有方法的封装
    • 高阶函数
    • 函数柯里化
    • 节流、防抖
  • 关于内存泄漏
    • 闭包本身并不会造成内存泄漏,除非代码书写有误
    • 但是对于 IE 来说,在 IE9 之前,对 JScript 对象和 COM 对象使用了不同的垃圾回收机制,所以闭包在这些旧版本 IE 中可能会导致问题。比如在这些版本的 IE 中,把 HTML 元素保存在某个闭包的作用域中,就相当于宣布该元素不能被销毁。
      • COM 对象:在 IE8 及更早的版本中,并非所有对象都是原生 JS 对象,BOM 和 DOM 中的对象是 C++ 实现的组件对象模型对象,简称 COM 对象。
      • JScript 早期微软公司为其 IE 浏览器引入的语言

参考资料

浏览知识共享许可协议

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。