• 我理解的闭包


    我觉得很多人都错误理解了闭包,或者说根本就不理解,只是人云亦云。

    维基百科对于闭包的描述:

    a closure is a record storing a function together with an environment: a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope)

    MDN对于闭包的描述:

    闭包是函数和声明该函数的词法环境的组合。

    “声明该函数的词法环境”即为函数的作用域链,因此可以说,一切函数都是闭包
    而一般狭义的理解是,闭包就是引用了外部变量的函数和这些变量

    const count = 0
    
    function getCount () {
      console.log(count)
    }
    
    function run () {
      const count  = 1
      getCount()
    }
    
    run()
    

    执行run的时候会发生什么?答案是打印'0',因为run里的getCount函数是一个闭包,包含了其声明时的外部变量count,因此count的值是外层的'0'。

    而大多数人,似乎把“利用闭包实现私有变量”当成了闭包本身。

    很多讲闭包的文章都会写这个计数器函数的例子:

    const increase = function ()  {
      let count = 0
      return function () {
         return ++count
      }
    }()
    increase() // 1
    increase() // 2
    

    他们一般会说“这就是闭包”,却说不清楚到底什么是闭包。

    函数内部的匿名函数,和其定义时的外部变量count,作为一个整体,就是闭包。

    接下来将这个闭包return并赋值给外层的变量increase, 使该闭包随着increase存在于内存中而不是被GC销毁。count能够完成计数的功能,说明其也存在于内存中,证明了变量也是闭包的一部分。

    大多数js库都会用一个自执行的匿名函数封装起来,正是利用了闭包的特性。以jQuery为例:

    (function (global, factory) {
      ...
    })(window, function (window) {
      var	version = "3.2.1"
      var support = {}
      var siblings = function () { ... }
      var jQuery = function () { ... }
      jQuery.prototype = { ... }
      ...
      window.jQuery = window.$ = jQuery
    })
    

    factory里定义的变量,在其他函数里被引用到,这些函数又成为了jQuery的原型方法,最后jQuery函数和内部的变量作为一个闭包,被“绑定”到window对象上。于是外层环境可以通过window.jQuery使用内部的变量和方法,却不能直接访问和修改。这就实现了私有变量和私有方法,同时还避免了污染全局环境。

    闭包的主要用途,正是用来封装私有变量和方法,避免污染全局环境。
    类似常见的用法还有函数debounce,throttle等。

    实际上除了这些常被提起用法,我们平常也经常用到闭包,举一个实际的例子:

    // api.js
    const axios = import('axios')
    const url = '/getUserInfo'
    
    export function getUserInfo() {
      return axios.get(url)
    } 
    
    // index.js
    const { getUserInfo } = import('./api')
    
    getUserInfo().then() ...
    
    

    函数getUserInfo访问了其外部的变量axios和url,而在index中并未定义这两者,为什么可以直接调用? 这正是因为被导入的getUserInfo是一个“闭包”:包含了函数本身和其作用域链上的变量的一个整体。

  • 相关阅读:
    继承
    对象与类
    反射
    I/O流
    字符串
    Map的entrySet()方法
    接口与内部类
    Git Usage Summary
    HTML(5)
    毕业设计:下载
  • 原文地址:https://www.cnblogs.com/huanglei-/p/7071202.html
Copyright © 2020-2023  润新知