返回顶部
首页 > 资讯 > 精选 >JavaScript 函数的闭包是怎样的
  • 114
分享到

JavaScript 函数的闭包是怎样的

2023-06-16 03:06:27 114人浏览 八月长安
摘要

javascript 函数的闭包是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 前言我们知道,作用域链查找标识符的顺序是从当前作用域开始一级一级往上查找。

javascript 函数的闭包是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

 前言
我们知道,作用域链查找标识符的顺序是从当前作用域开始一级一级往上查找。因此,通过作用域链,JavaScript函数内部可以读取函数外部的变,但反过来,函数的外部通常则无法读取函数内部的变量。在实际应用中,有时需要真正在函数外部访问函数内部的局部变量,此时最常用的方法就是使用闭包。

那么什么是闭包?所谓闭包,就是同时含有对函数对象以及作用域对象引用的对象。闭包主要是用来获取作用域链或原型链上的变量或值。创建闭包最常见的方式是在一个函数中声明内部函数(也称嵌套函数),并返回内部函数。此时在函数外部就可以通过调用函数得到内部函数。虽然按照闭包的概念,所有访问了外部变量的JavaScript函数都是闭包。但我们平常绝大部分时候所谓的闭包其实指的就是内部函数闭包。
闭包可以将一些数据封装私有属性以确保这些变量的安全访问,这个功能给应用带来了极大的好处。需要注意的是,闭包如果使用不当,也会带来一些意想不到的问题。下面就通过几个示例来演示一下闭包的创建、使用和可能存在的问题及其解决方法。
示例1: 创建闭包。

<!DOCTYPE html> <html> <head>  <title>闭包</title> </head> <body> <script type="text/javascript">  function outer(argument) {   var b=0;   return function inner (){    b++;    console.log("内部的b:"+b);   }  }  var func =  outer();//1 通过外部变量引用函数返回的内部函数  console.log(func);//2 输出内部函数定义代码  func();//3 通过闭包访问局部变量b,此时b=1;  console.log("外部函数中b:"+b); //4 出错,报引用错误。 </script> </body> </html>

上述代码在外部函数outer中声明内部函数inner,并返回内部函数,同时在outer函数外面,变量func引用了outer函数返回的内部函数,所以内部函数inner是一个闭包。该闭包访问了外部函数的局部变量b。1处代码通过调用外部函数返回内部函数并赋给外部变量func,使func变量引用内部函数,所以2处代码将输出inner函数的整个定义代码。3处代码通过对外部变量func添加一对小括号后调用内部函数inner,从而达到在函数外部访问局部变量b的目的。执行4处的代码时将报ReferenceError错误,因为b是局部变量,不能在函数外部直接访问局部变量。
我们知道函数执行完毕时,运行期上下文会被销毁,与之关联的活动对象也会随之销毁,因此离开函数后,属于活动对象的局部变量将不能被访问。但是为什么上述示例中的outer函数执行完后,它的局部变量还能被内部函数访问呢?这个问题我们可以用作用域链来解释。
当执行1处代码调用outer函数时,JavaScript引擎会创建outer函数执行上下文的作用域链,这个作用域链包含了outer函数执行时的活动对象,同时JavaScript引擎也会创建一个闭包,而闭包因为需要访问outer函数的局部变量,因而其作用链也会引用outer的活动对象。这样,当outer函数执行完后,它的作用域对象因为有闭包的引用而依然存在,固而可以提供给闭包访问。
上述示例中的内部函数虽然有名称,但在调用是并没有用到这个名称,所以内部函数的名称可以缺省,即可以将内部函数修改为匿名函数,从而简化代码。
示例2: 经典闭包问题

<!DOCTYPE html> <html> <head> <title>经典闭包问题</title> <script type="text/javascript">  window.onload=function () {   var abtn = document.getElementsByTagName("button");   for (var i = 0; i<abtn.length; i++) {    abtn[i].onclick=function(){     alert("按钮"+(i+1));    }   }  } </script> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> </body> </html>

该示例期望实现的功能是,单击每个按钮时,在弹出的警告对话框中显示相应的标签内容,即单击3个按钮时将分别显示“按钮1”、“按钮2”、“按钮3”。
上述示例页面加载完后触发窗口加载事件,从而执行外层匿名函数,外层匿名函数执行完循环语句后使活动对象中的局部变量i的值修改为3。外层匿名函数执行完后撤销,但由于其活动对象中的abtn和i变量被内层匿名函数引用,因而外层匿名函数的活动对象仍然存在堆中供内层匿名函数访问。每执行一次循环都将创建一个闭包,这些闭包都引用了外层匿名函数的活动对象,因而访问变量i时都得到3,这样最后的结果是单击每个按钮,在警告对话框中显示的文字都是“按钮4” (i+1=3+1),与期望的功能不一致。造成这个问题的原因是,每个闭包都引用一个变量,如果我们使不同的闭包引用不同的变量,就可以实现输出的结果不一样。这个需求可使用多种方法实现,在此介绍使用立即调用函数表达式(IIFE)和es6中的let创建块即变量的方法。
IIFE指的是:在定义函数的时候直接执行,即此时函数定义变成了一个函数调用的语句。要让一个函数定义语句变成函数调用语句,就需要将定义语句变为一个函数表达式,然后在该表达式后面再加一对圆括号()即可。将函数定义语句变为一个函数表达式的最常用方法就是将整个定义语句放在一对圆括号中。
1、IIFE中的函数为一个匿名函数

(function(name){  console.log("hello,"+name); })("maomin");

js引擎执行上述代码时,会调用匿名,同时将后面圆括号中的参数maomin传给name虚参,结果得到:"hello,maomin"。
2、IIFE中的函数为一个有名函数

(function func (name) {  console.log("I am"+name); })("maomin")

上述代码跟匿名函数完全一样。

示例3: 使用立即调用函数表达式解决经典闭包问题

<!DOCTYPE html> <html> <head>  <title>使用立即调用表达式解决经典闭包问题</title>  <script type="text/javascript">  window.onload=function () {   var abtn = document.getElementsByTagName("button");   for (var i = 0; i<abtn.length; i++) {    (function(num){     abtn[num].onclick=function(){         alert("按钮"+(num+1));        }    })(i)   }  } </script> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> </body> </html>

上述代码中第二个匿名函数为IIFE,每次调用该匿名函数时将生成一个对应该函数的活动对象。该对象中包含可一个函数参数,值为当次循环的循环变量值。上述示例中,IIFE共执行了3次,因而共生成了3个活动对象,活动对象中包含的参数值分别为0、1和2,依次对应IIFE的3次执行。
每次执行IIFE时,将会产生一个闭包,该闭包会引用对应按钮索引顺序执行IIFE的活动对象,而闭包引用的活动对象中的参数值刚好等于按钮的索引值,因而单击3个按钮将在弹出的警告框中分别显示"按钮1"、“按钮2”、“按钮3”。
示例4:使用ES6中的let关键字创建块级变量解决经典闭包问题

<!DOCTYPE html> <html> <head>  <title>使用ES6中的let关键字解决经典闭包问题</title>  <script type="text/javascript">  window.onload=function () {   var abtn = document.getElementsByTagName("button");   for (let i = 0; i<abtn.length; i++) {    abtn[i].onclick=function(){     alert("按钮"+(i+1));    }   }  } </script> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> </body> </html>

上述代码中循环变量使用let声明,因而每次循环时,都会产生一个新的块级变量,所以在页面加载完,执行外层匿名函数时产生的活动对象中包含了3个对应循环变量的块级变量,变量值分为0、1和2。每执行一次循环,将会产生一个闭包,该闭包中的变量i会引用外层匿名函数的活动对象对应按钮索引的块级变量,因而单击3个按钮时将在弹出的警告对话框中分别显示“按钮1”、“按钮2”、“按钮3”。

关于JavaScript 函数的闭包是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: JavaScript 函数的闭包是怎样的

本文链接: https://lsjlt.com/news/282166.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaScript 函数的闭包是怎样的
    JavaScript 函数的闭包是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 前言我们知道,作用域链查找标识符的顺序是从当前作用域开始一级一级往上查找。...
    99+
    2023-06-16
  • JavaScript 闭包与高阶函数是怎样的
    JavaScript 闭包与高阶函数是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。「JavaScript 中,函数是一等公民」,在各种...
    99+
    2024-04-02
  • JavaScript中的闭包是怎样的
    这篇文章给大家介绍JavaScript中的闭包是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 闭包的概念来看一般函数的执行和启发:function stop() {  ...
    99+
    2023-06-22
  • 怎样解析javascript的闭包
    今天就跟大家聊聊有关怎样解析javascript的闭包,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。什么是闭包:闭包是一个存在内部函数的引用关系。该引用指向的是外部函数的局部变量对象...
    99+
    2023-06-29
  • 在JavaScript函数中什么是闭包
    本篇内容介绍了“在JavaScript函数中什么是闭包”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!匿名函...
    99+
    2024-04-02
  • 怎么理解JavaScript闭包函数
    本篇内容介绍了“怎么理解JavaScript闭包函数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!变量作用域要理解JavaScript闭包,...
    99+
    2023-06-25
  • JavaScript 函数闭包的含义和作用是什么
    这篇文章主要讲解了“JavaScript 函数闭包的含义和作用是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript 函数闭包的含义和作用...
    99+
    2024-04-02
  • JavaScript闭包和匿名函数的关系
    这篇文章主要讲解了“JavaScript闭包和匿名函数的关系”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript闭包和匿名函数的关系”吧!前面...
    99+
    2024-04-02
  • golang函数的闭包
    闭包是在嵌套函数中定义的函数,可以访问嵌套函数作用域中的变量,包括返回值已返回后的变量。它们用于创建灵活可重用的代码,例如生成斐波那契数列的项:定义一个生成斐波那契项的闭包函数。闭包函数...
    99+
    2024-04-19
    golang 闭包 作用域
  • JavaScript函数闭包实例讲解
    这篇文章主要讲解了“JavaScript函数闭包实例讲解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript函数闭包实例讲解”吧!首先让我们来...
    99+
    2024-04-02
  • JavaScript(函数,作用域和闭包)
    目录 一,什么是函数1.1,常用系统函数1.2,函数声明 1.3,函数表达式二,预解析2.1,函数自调用 2.2,回调函数三,变量的作用域3.1,隐式全局变量 四,作用域与块级作用...
    99+
    2023-09-05
    前端 javascript 开发语言
  • 一文了解JavaScript闭包函数
    目录变量作用域闭包的概念闭包的用途闭包的缺点最后总结一下闭包的好处与坏处总结变量作用域 要理解JavaScript闭包,就要先理解JavaScript的变量作用域。 变量的作用域有...
    99+
    2024-04-02
  • javascript之匿名函数和闭包的示例分析
    小编给大家分享一下javascript之匿名函数和闭包的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体内容如下匿名函数<script type="te...
    99+
    2024-04-02
  • golang函数中的闭包是如何实现的?
    go中函数闭包通过嵌套函数实现,允许内部函数访问外部函数作用域的变量。具体步骤如下:定义外部函数,接收参数并返回闭包函数。定义闭包函数,内部访问外部函数变量。返回闭包函数,即使外部函数已...
    99+
    2024-05-24
    golang 闭包 作用域
  • JavaScript中的闭包
    一.什么是闭包 1.闭包的定义 闭包并不是JS特有的,因此可以从两个角度定义闭包。 1)计算机科学中 闭包又称为词法闭包(在进行词法分析的时候这个闭包就确定了),或者是函数闭包。是在支持头等函数的编程语言中(意思是函数作为一等公民的编程语言...
    99+
    2023-08-18
    javascript 前端 java
  • Javascript闭包的作用是什么
    本篇内容主要讲解“Javascript闭包的作用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Javascript闭包的作用是什么”吧!对于初学者来说,理...
    99+
    2024-04-02
  • Javascript闭包的特性是什么
    本篇内容介绍了“Javascript闭包的特性是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java...
    99+
    2024-04-02
  • javascript中什么指的是闭包
    这篇文章主要为大家展示了“javascript中什么指的是闭包”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“javascript中什么指的是闭包”这篇文章吧。 ...
    99+
    2024-04-02
  • javascript的闭包是什么意思
    这篇文章将为大家详细讲解有关javascript的闭包是什么意思,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 在javascript中,当两...
    99+
    2024-04-02
  • php中闭包函数的作用是什么
    这篇文章给大家分享的是有关php中闭包函数的作用是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是闭包函数:在子函数内部使用通过use关键字使用父函数的变量,这种方式就是闭包函数格式:function&n...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作