草庐IT

闭包

不见水星记 2023-03-28 原文

一、作用域

  • JavaScript作用域:分为全局作用域、局部作用域。变量在某个范围内起作用和效果,目的是为了提高程序的可靠性和减少命名冲突。

  • 变量的作用域:根据作用域的不同我们变量分为全局变量和局部变量。两种变量其主要区别是函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

  • 作用域链:

    • 根据内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链

    • 只要是代码,就至少有一个作用域。

    • 写在函数内部的局部作用域。

    • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

1.全局变量
  • 概念:在全局作用域下的变量,在全局下都可以使用。
  • 如果在函数内部没有声明直接赋值的变量也属于全局变量。
  • 只有浏览器关闭的时,全局变量才会销毁,比较占内存资源。
    • 全局作用域:整个script标签中,或者是一个单独的js文件。
2.局部变量
  • 在局部作用域下变量,即在函数内部的变量就是局部变量,只能在函数内部使用。
  • 函数的形参也可以看做是局部变量。
  • 当我们程序执行完毕时,局部变量就会销毁,比较节约内存资源。
    • 局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字(变量)只在函数内部起作用和效果。

二、理解闭包

1.闭包的概念
  • 闭包是指有权访问另外一个函数作用域中的局部变量的函数。声明在一个函数中的函数,叫做闭包函数。而且内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
2.闭包的特点
  • 让外部访问函数内部变量成为可能。
  • 局部变量会常驻在内存中。
  • 可以避免使用全局变量,防止全局变量污染。
  • 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)。
3.闭包的分析
  • 闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,并且互不干扰。
  • 闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。
  • 但当外部函数运行结束甚至销毁时,局部的变量key=value,尽管key被垃圾回收机制给回收了,但是value仍不会被回收,会变成一个自由变量留下引用的指针。
4.闭包的实现案例
  • 利用闭包的方式,输出点击项的索引值

    <ul class="closure">
        <li>苹果</li>
        <li>香蕉</li>
        <li>橘子</li>
        <li>西瓜</li>
    </ul>
    <script>
    	// 获取所有的li元素
    	let lis = document.querySelectorAll('.closure li')
        // 利用for循环创建了4个立即执行函数
        for (let i = 0; i < lis.length; i++) {
            (function (i) {
                lis[i].addEventListener('click', function () {
                    console.log(i)
                })
            })(i)
        }
    </script>
    
  • 利用闭包的方式,3秒钟之后,打印所有li元素的内容

    <ul class="closure">
        <li>苹果</li>
        <li>香蕉</li>
        <li>橘子</li>
        <li>西瓜</li>
    </ul>
    <script>
    	// 获取所有的li元素
    	let lis = document.querySelectorAll('.closure li')
        for (let i = 0; i < lis.length; i++) {
            (function (i) {
                setTimeout(() => {
                    console.log(lis[i].innerHTML)
                }, 3000)
            })(i)
        }
    </script>
    

有关闭包的更多相关文章

  1. ruby - Ruby 中的闭包和 for 循环 - 2

    我是Ruby的新手,有些闭包逻辑让我感到困惑。考虑这段代码:array=[]foriin(1..5)array[5,5,5,5,5]这对我来说很有意义,因为i被绑定(bind)在循环之外,所以每次循环都会捕获相同的变量。使用每个block可以解决这个问题对我来说也很有意义:array=[](1..5).each{|i|array[1,2,3,4,5]...因为现在每次通过时都单独声明i。但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?array=[]foriin1..5j=iarray[5,5,5,5,5]因为j每次循环都是新的,我认为每次循环都会捕获不同的变量。例如,这绝对

  2. ruby - 如何 `break` 闭包中的外部循环(Proc,lambda)? - 2

    loop{break}可以正常工作,但是block=Proc.new{break}#or#block=lambda{break}loop(&block)#=>LocalJumpError:breakfromproc-closure是否可以在block变量中中断?更新:举例说明:defodd_loopi=1loopdoyieldii+=2endenddefeven_loopi=2loopdoyieldii+=2endend#Thisworkodd_loopdo|i|putsibreakifi>10end#Thisdoesn'tworkbreak_greater_10=Proc.newdo

  3. ruby - 在 Ruby 中定义一个闭包方法 - 2

    我正在用ruby​​重新定义对象中的方法,我需要新方法作为闭包。例如:defmess_it_up(o)x="blahblah"defo.to_sputsx#Wrong!xdoesn'texistshere,amethodisnotaclosureendend现在如果我定义一个Proc,它就是一个闭包:defmess_it_up(o)x="blahblah"xp=Proc.new{||putsx#Thisworksend#buthowdoIsetittoo.to_s.defo.to_sxp.call#sameproblemasbeforeendend有什么想法吗?谢谢。

  4. ruby - Ruby 中的闭包 - 2

    我在闭包方面遇到了一些麻烦,我想知道是什么规范的make-adder过程的等效代码将在ruby。在计划中它会是这样的:(define(make-addern)(lambda(x)(+xn)) 最佳答案 其实很接近...defmake_addrnlambda{|x|x+n}endt=make_addr100t.call1101在1.9中你可以使用...defmake_addrn->(x){x+n}end 关于ruby-Ruby中的闭包,我们在StackOverflow上找到一个类似的问题:

  5. javascript - "return () => local;"在这个闭包中做了什么? - 2

    我正在通过阅读“EloquentJavascript”学习javascript,但对第3章(函数)中的“闭包”部分感到困惑。在前面的部分中,我了解了箭头函数,以及如何将它们用作匿名函数。我最初的想法是,这是一个匿名函数示例,我只是还不熟悉。特别是,我对“()=>local”对返回/返回的作用感到困惑。functionwrapValue(n){letlocal=n;return()=>local;}letwrap1=wrapValue(1);letwrap2=wrapValue(2);console.log(wrap1());//→1console.log(wrap2());//→2这是

  6. JavaScript 闭包 - 使用 ECMA 规范,请解释闭包是如何创建和维护的 - 2

    我正在阅读JavaScriptclosures.我熟悉ExecutionContexts,如何LexicalEnvironment维护的,很熟悉LexicalScoping.我想知道JavaScript中的闭包是如何创建和维护的。有时,如果不了解它的实际操作方式,我很难掌握如此重要的概念。我知道,根据维基百科,闭包是isafunctionorreferencetoafunctiontogetherwithareferencingenvironment—atablestoringareferencetoeachofthenon-localvariables(alsocalledfreev

  7. javascript - 防止 JavaScript 闭包继承作用域 - 2

    我正在寻找一种奇特的方法来防止闭包继承周围的范围。例如:letfoo=function(t){letx='y';t.bar=function(){console.log(x);//=>'y'});};我只知道两种方法来阻止共享范围:(1)使用影子变量:letfoo=function(t){letx='y';t.bar=function(x){console.log(x);//=>'?'});};(2)把函数体放在别处:letfoo=function(t){letx='y';t.bar=createBar();};我的问题是-有谁知道防止闭包继承JS范围的第三种方法吗?花哨的东西很好。我

  8. 闭包中的 javascript 原型(prototype)和 "this"访问 - 2

    我是js新手,对下面的代码很疑惑:Foo=function(arg){this.arg=arg;};Foo.prototype={init:function(){varf=function(){alert("currentarg:"+this.arg);//amexpecting"bar",gotundefined}f();}};varyo=Foo("bar");yo.init();我应该得到“currentarg:bar”,但得到的是“currentarg:undefined”。我注意到首先将this.arg复制到一个“普通”变量中,然后在闭包中引用这个变量:Foo.prototyp

  9. javascript - 使用闭包编译器进行类型检查不是隐式的吗? - 2

    我正在编译文件并获得可运行的编译代码,但注释似乎被完全忽略了;没有警告没有错误。使用calcdeps.py通过以下命令编译我的代码:setcalc="D:\software\closurecompiler\library\closure\bin\calcdeps.py"c:\Python27\python.exe%calc%^--pathD:\flex_sdk_4.6\projects\EnglishConverter\bin\js\^--inputD:\flex_sdk_4.6\projects\EnglishConverter\bin\js\mmt\Mediator.js^--in

  10. javascript - 构造函数与闭包? - 2

    这2个对象a使用构造函数创建,b使用闭包创建,究竟有什么不同?属性__proto__是否对使用闭包无法实现的任何事情有用?我应该在不同的情况下使用这些技术吗?内存使用有区别吗?(jsFiddle)window.MODULE={};MODULE.constructor=function(){this.publicVariable=10;};MODULE.constructor.prototype.publicMethod=function(){returnthis.publicVariable;};//-------------------------------//MODULE.clo

随机推荐