闭包是什么?

骑猪看日落 2021-09-14 11:32 490阅读 0赞

1.什么是闭包?
古老定义
  闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量“包裹”了起来

  那这样说来,包含变量的函数就是闭包

  1. //按照古老定义,包含变量n的函数foo就是闭包
  2. function foo() { var n = 0; } console.log(n)//Uncaught ReferenceError: n is not defined

定义一
  闭包是指可以访问其所在作用域的函数

  那这样说来,需要通过作用域链查找变量的函数就是闭包

  1. //按照定义一的说法,需要通过作用域链在全局环境中查找变量n的函数foo()就是闭包
  2. var n = 0;
  3. function foo() {
  4. console.log(n)//0
  5. }
  6. foo();

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

  那这样说来,访问上层函数的作用域的内层函数就是闭包

  1. //按照定义二的说法,嵌套在foo函数里的bar函数就是闭包
  2. function foo(){
  3. var a = 2;
  4. function bar(){
  5. console.log(a); // 2
  6. }
  7. bar();
  8. }
  9. foo();

定义三
  闭包是指在函数声明时的作用域以外的地方被调用的函数

  在函数声明时的作用域以外的地方调用函数,需要通过将该函数作为返回值或者作为参数被传递

【1】返回值

  1. //按照定义三的说法,在foo()函数的作用域中声明,在全局环境的作用域中被调用的bar()函数是闭包
  2. function foo(){
  3. var a = 2;
  4. function bar(){
  5. console.log(a); //2
  6. }
  7. return bar;
  8. }
  9. foo()();

  可以简写为如下表示:

  1. function foo(){
  2. var a = 2;
  3. return function(){
  4. console.log(a);//2
  5. }
  6. }
  7. foo()();

【2】参数

  1. //按照定义三的说法,在foo()函数的作用域中声明,在bar()函数的作用域中被调用的baz()函数是闭包
  2. function foo(){
  3. var a = 2;
  4. function baz(){
  5. console.log(a); //2
  6. }
  7. bar(baz);
  8. }
  9. function bar(fn){
  10. fn();
  11. }

  因此,无论通过何种手段,只要将内部函数传递到所在的词法作用域以外,它都会持有对原始作用域的引用,无论在何处执行这个函数都会使用闭包

IIFE
  IIFE是不是闭包呢?

  foo()函数在全局作用域定义,也在全局作用域被立即调用,如果按照定义一的说法来说,它是闭包。如果按照定义二和定义三的说法,它又不是闭包

  1. var a = 2;
  2. (function foo(){
  3. console.log(a);//2
  4. })();

  还有一个更重要的原因是,在requireJS出现之前,实现模块化编程主要通过IIFE,而在IIFE中常见的操作就是通过window.fn = fn来暴露接口,而这个fn就是闭包,而IIFE只是一个包含闭包的函数调用

  1. (function(){
  2. var a = 0;
  3. function fn(){
  4. console.log(a);
  5. }
  6. window.fn = fn; })()
  7. fn();

最后

  闭包定义之所以混乱,我觉得与经典书籍的不同解读有关。经典定义是犀牛书的原话,定义二是高程的原话

  但,归纳起来就是关于一个函数要成为一个闭包到底需要满意几个条件

  严格来说,闭包需要满足三个条件:【1】访问所在作用域;【2】函数嵌套;【3】在所在作用域外被调用

使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

闭包有三个特性:

1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收

发表评论

表情:
评论列表 (有 0 条评论,490人围观)

还没有评论,来说两句吧...

相关阅读

    相关 什么

    我们都知道一个概念。 在JS当中,一个函数可以访问其外部的变量资源。 ![format_png][] 一个典型的代码   但以下这种情况会出错。 fun

    相关 什么

    闭包 我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的

    相关 什么

            \----本文摘自programming in  lua 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包

    相关 什么

    什么是闭包? 简单来说,闭包是指外部可以访问另一个函数作用域内的变量的函数,一般是定义在外层函数中的内层函数。 为什么需要闭包? 局部变量无法共享和长久的保存,而全局变量

    相关 什么

    闭包是指有权访问另一个函数作用域中变量的函数 作用:访问另一个函数作用域中变量 原理:通过匿名式函数把局部变量驻留在内存里,可以减少全局变量的使用 优点是封装性,

    相关 什么

    什么是闭包? 说明 闭包   有些读者可能很好奇,为什么闭包会成为一个独立的概念,以及为什么它需要编程语言提供额外的支持。这些疑惑可以本文中找到答案。

    相关 什么

    1.什么是闭包? 古老定义   闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量“包裹”了起来   那这样说来,包含变量的函数就是闭

    相关 什么

    闭包 定义:闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链