闭包

JavaScript 什么是闭包免费看

什么是闭包、变量作用域、如何在函数体外使用局部变量、闭包的用途

2020-06-18侠课岛    基础入门       

前端/前端必修/JavaScript 基础知识梳理 12     0     608

本节我们学习闭包,闭包是 JavaScript 语言的一个很重要的知识点。

那什么是闭包呢,在 JavaScript 中变量分为全局变量和局部变量,全局变量是全局都可以访问的,而局部变量在只有函数内部或函数内部的子函数才能访问,函数外部无法访问。因此我们可以将闭包理解成 “定义在一个函数内部的函数”。

在本质上来说,闭包是将函数内部和函数外部连接起来的一座桥梁,通过闭包我们可以在函数外部访问到函数内部的变量。

变量作用域

我们要理解闭包,首先需要弄清楚 JavaScript 中特殊的变量作用域。变量的作用域分为两种,全局变量和局部变量。其实我们通过这两个名字就大概能有一点区分。

  • 全局变量:定义在函数体外的变量叫做全局变量。全局变量既能在函数体外使用,又能在函数体内使用。
  • 局部变量:定义在函数体内的变量叫做局部变量。局部变量只能在函数体内使用。
示例:

下图中变量a为全局变量,变量b为局部变量:

从上图我们可以看出,局部变量只能在定义它函数内部使用。

不过有一点需要特别注意,如果声明变量时没有使用 var 关键字,那么这个变量就是一个全局变量,不管它是否定义在函数体内。

function num(){
  name = "侠课岛";
}
num();

// 在函数外部使用变量name
console.log(name);   // 输出:侠课岛

例如上述代码中,我们在函数体内定义了变量 name,但是没有使用关键字 var,在函数体外也可以使用这个变量。

如何在函数体外使用局部变量

上面讲了局部变量不能在函数体外使用,那如果我们必须要使用函数的局部变量呢,有另外一个方法来实现,就是在函数的内部,再定义一个函数。

首先我们来看下面这段代码,我们在fun_out 函数内,定义了一个fun_in函数:

function fun_out(){
  var num1 = 100;
  function fun_in(){
    console.log(num1);  // 输出:100
  }
  // 调用fun_in函数
  fun_in();
}
fun_out();

因为函数 fun_in 是包含在函数 fun_out 中,所以 fun_in 函数可以访问 fun_out 中的所有局部变量。

但是反过来,fun_in 中的局部变量,在fun_in之外是不能访问的。这就是 JavaScript 语言中的链式作用域结构,子对象会一级一级地向上寻找所有父对象的变量。

那么既然 fun_in 可以使用 fun_out 中的局部变量,那么如果我们将 fun_in 作为返回值,我们不就可以在 fun_out 外部读取它的内部变量了吗。

例如下面这段代码:

function fun_out(){
  var num1 = 100;
  function fun_in(){
    console.log(num1);  
  }
  return fun_in;
}
var result = fun_out();
result(); // 100

其中 fun_in 函数就是一个闭包。你可以将闭包理解成可以读取其他函数内部变量的函数,fun_in 可以读取fun_out 函数对吧,fun_in 是一个函数对吧,那么 fun_in 就可以看成一个闭包。

闭包的用途

闭包可以使用在很多地方,例如它能够读取其他函数内部变量,还可以让这些变量的值始终保持在内存中等。

示例:
function fun_out(){
  var num1 = 100; // 局部变量
  // add没有使用var,所以是一个全局变量
  add = function(){
    num1 += 100;
  }

  function fun_in(){
    console.log(num1);  
  }
  return fun_in;
}
var new_fun = fun_out();
new_fun(); // 100
add();
new_fun(); // 200

在上述代码中,因为fun_in 作为 fun_out 函数的返回值,所以其实我们将 fun_out() 赋给变量new_fun,就相当于将 fun_in 赋给了 new_fun 变量。不信我们可以输出看看:

console.log(fun_out());  // 输出:[Function: fun_in]

所以 new_fun 实际上就是闭包 fun_in 函数,而我们一共调用了 new_fun() 两次,分别输出了 100 和 200 。这说明 fun_out 中的局部变量 num1 一直保存在内存中,并没有在调用后被清空。

这是因为fun_outfun_in 的父函数,而 fun_in 被赋给了一个全局变量,这导致 fun_in 会一直在内存中,而 fun_infun_out 函数中,所以 fun_out 也会一直在内存中,不会在调用后被回收 。

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。

本教程图文或视频等内容版权归侠课岛所有,任何机构、媒体、网站或个人未经本网协议授权不得转载、转贴或以其他方式复制发布或发表。

评价

12

本课评分:
  •     非常好
难易程度:
  •     适中的

内容目录


本文索引


|
教程
粉丝
主页

签到有礼

已签到2天,连续签到7天即可领取7天全站VIP

  • 1
    +2 金币
  • 2
    +3 金币
  • 3
    +5 金币
  • 6
    +7 金币
  • 5
    +6 金币
  • 4
    暖心福利
    自选分类VIP ×1天
  • 7
    惊喜大礼

    自选分类VIP ×3天 +20金币
  • 持续签到 +8 金币

金币可以用来做什么?