首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

我从来不理解JavaScript闭包,直到有人这样向我解释它

这里提到了自由变量,它又是什么呢? 自由变量可以理解成跨作用域的变量,比如子作用域访问父作用域的变量。...如下代码中,console.log(a)  要得到 a 变量,但是在当前的作用域中没有定义 a(可对比一下 b)。当前作用域没有定义的变量,这成为自由变量 。...} test(); 在上面的代码中,我们 test 函数中访问了自由变量 stuName,这个被引用自由变量将和这个函数一同存在。...局部变量本来应该在函数退出时被解除引用,但如果局部变量封闭闭包形成的环境中,那么这个局部变量就能一直生存下去。也就是说,闭包会将局部变量保存下来。...如果大量使用闭包,而其中的变量又未得到清理,闭包的确会使一些数据无法被及时销毁,从而造成内存泄漏。 但是使用闭包的一部分原因,是我们选择主动把一些变量封闭闭包中,因为可能在以后还需要使用这些变量

30850

从λ演算到函数式编程聊闭包(1):闭包概念在JavaPHPJS中形式

,是引用自由变量的函数。...这个被引用自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 Peter J....“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。...闭包概念: 闭包就是有权访问另一个函数作用域中变量的函数....而f的作用域为(f 7),这就是说,其实在(f 7)之后,f这个函数就结束了,而x(这里被赋值为7)是f的私有变量(绑定于f),那么程序设计语言的设计者就有两种选择: 第一,函数超出其作用域后立即销毁其绑定变量

76310
您找到你想要的搜索结果了吗?
是的
没有找到

《你不知道的js(上卷)》笔记1(基础知识和闭包)

当引擎执行LHS查询时,如果在全局作用域中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是非 “严格模式”下。...函数作用域的是指,属于这个函数的全部变量都可以整个函数的范围内(包括嵌套的作用域中)使用及复用。...,尽管循环中的五个函数是各个迭代中分别定义的, 但是它们都被封闭一个共享的全局作用域中,因此实际上只有一个i。...由于函数延迟执行,最终循环执行完才调用,得到i的值为6。 例2.2:匿名函数有自己的作用域,变量j用来每个迭代中储存i的值。 例2.3:对例2.2代码的改进。...迭代内使用IIFE会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用封闭每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问。

42620

经典面试题解析

var a=[]; var i=0; /* 用var声明的变量要么函数作用域中,要么全局作用域中,很明显这里是全局作用域中, 因此认为i是全局变量,直接放在全局变量中。...i,所以i为自由变量,此时会 沿着作用域链向上寻找,进而进入了全局作用域中寻找变量i,而全局作用域 中的i循环跑完后已经变成了10,所以a[6]的值就是10了。...在这个块级作用域中,而不是全局作用域中。...*/ a[0]=function(){ console.log(i); }; /* 注意:由于是用let声明的i,所以使整个块成为块级作用域,又由于a[0]这个函数 引用到了上一级作用域中自由变量...*/ 讲道理,上面这是一个块级作用域,就像函数作用域一样,执行完毕,其中的变量会被销毁, 但是因为这个块级作用域中存在一个闭包,且该闭包维持着对自由变量i的引用,所以闭包 被调用之前也就是后续为了测试而

59940

Python与家国天下

这时候, locals() 局部命名空间中也是没有内容的(读者可以试一下)。但是 print 方法却报找到了一个未赋值变量 x ,这是为什么呢?...LOAD_FAST 说明它在局部作用域中找到了变量名 x,结果 0 说明未找到变量 x 所指向的值。既然此时 locals() 局部命名空间中没有内容,那局部作用域中找到的 x 是来自哪里的呢?...在编译期之后,局部作用域内的变量名已经确定了,只是没有赋值随后的解释期(即代码执行期),如果有赋值过程,则变量名与值才会被存入局部命名空间中,可通过 locals() 查看。...可以推论:局部作用域中查找变量,实际上是分查内存与查命名空间两步的。另外,若想在局部作用域内修改全局变量,需要在作用域中写上 “global x”。...上例是一个求平均值的函数,由于自由变量的存在,每次调用时,新传入的参数会跟自由变量一起计算。 计算机科学中,引用自由变量的函数被称为闭包(Closure)。

51320

Python Closure

计算机科学中,闭包 又称 词法闭包 或 函数闭包,是引用自由变量的函数。这个被引用自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。闭包被广泛应用于函数式语言中。...从上面这段话中可以看出闭包的两个重要条件是引用自由变量和函数,与闭包这个名称结合起来看,这个函数就像是一个包,而这个函数所引用变量就好比函数这个包中封闭起来的东西,包中的东西被紧紧封闭包中,函数所引用变量也被与这个函数所绑定...,Nested function指的被定义一个函数(outer enclosing function)中的函数,这个nested function可以调用包围它的作用域中变量。...父函数返回了这个Nested function 闭包主要运用在需要讲父函数作用域中变量绑定到子函数的场景之中,释放掉父函数之后子函数也不会受到影响。...__closure__ (,) 尽管这两个引用都被存在同意个cell object,但是他们仍然只各自的作用域下作用

28810

JS作用域与闭包

2|0全局作用域 全局作用页面打开时创建,页面关闭时销毁。 全局作用域中,创建的变量都会作为window对象的属性保存; 创建的函数都会作为window对象的方法保存。...变量函数外定义就是全局变量全局作用域中有一个全局对象window,可以直接使用。 全局作用域中变量都是全局变量页面的任意部分都可以访问到。...函数作用域中,可以访问到全局作用域的变量,全局作用域中无法访问到函数作用域的变量。...当在函数作用域操作一个变量时,会现在自身作用域中寻找,如果有就直接使用,如果没有则向上一级作用域中寻找函数作用域中也有声明提前的特性使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 function...5|0闭包 闭包是一个可以访问外部(封闭)函数作用域链中变量的内部函数。

1.9K20

深入理解JavaScript闭包之什么是闭包

bar() 依然持有对该作用域的引用,这个引用就叫做闭包。这个函数定义的词法作用域以外的地方被调用。闭包使得函数可以继续访问定义时的词法作用域。...用一句话描述:闭包是指有权访问另一个函数作用域中变量的函数。创建闭包最常见的方式就是,一个函数内部创建另一个函数。...但是实际上,根据作用域的原理,尽管循环中的五个函数都是各自迭代中分别定义的,但是他们都封闭一个共享的全局作用域中,因此实际上只有一个 i。即所有函数共享一个 i 的引用。...这样修改之后,每次迭代内使用 IIFE(立即执行函数)会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用封闭每个迭代内部,每个迭代内部都会含有一个具有正确值的变量可以访问。...()() 返回 “my Object” arguments 和 this存在相同的问题,如果想访问作用域中的 arguments 对象,必须将对该对象的引用保存到另一个闭包能够访问的变量中。

80630

python基础教程:作用域和命名空间

执行期间的任何时刻,至少有三个嵌套的作用域,它们的命名空间可以直接访问: 最内部作用域:最先搜索该作用域,包含局部名称 封闭函数作用域:从最近的封闭作用域开始搜索,包含非局部名称,也包括非全局名称 倒数第二个作用域...:包含当前模块的全局名称 最外面的作用域:最后搜索,是包含内置名称的命名空间 如果一个名称被声明为全局变量,则所有引用赋值将直接指向包含该模块的全局名称的中间作用域。...如果没有被声明为非本地变量,这些变量将是只读的(尝试写入这样的变量只会在最内层作用域中创建一个新的局部变量,而同名的外部变量保持不变)。...删除也是如此,语句del x会从局部命名空间的引用中移除对x的绑定。事实上,所有引入新名称的操作都使用局部作用域,特别是import语句和函数定义会在局部作用域中绑定模块或函数名称。...global语句可被用来表明特定变量生存于全局作用域并且应当在其中被重新绑定;nonlocal语句表明特定变量生存于外层作用域中并且应当在其中被重新绑定。

56240

go 学习笔记之仅仅需要一个示例就能讲清楚什么闭包

(本地使用但在封闭范围内定义的变量)与创建闭包时名称绑定到的值或引用相关联。...自由变量 这里使用了一个比较陌生的概念: 自由变量(本地使用但在封闭范围内定义的变量) 很显然,根据括号里面的注释说明我们知道: 所谓的自由变量是相对于闭包函数或者说匿名函数来说的外部变量,由于该变量的定义不受自己控制...a } } 变量 a,b 定义函数 fibonacci 内部,相对于匿名函数 func() int 来说是自由变量,匿名函数中直接使用了变量 a,b 并没有重新复制一份,所以这种形式的环境关联的自由变量引用...a,b 的值或引用,定义函数内部是无法暴露给调用者访问的,只能提升成全局变量才能实现作用域范围的扩大....怎么理解闭包 闭包是一种函数式编程中实现名称绑定的技术,直观表现为函数嵌套提升变量作用范围,使得原本寿命短暂的局部变量获得长生不死的能力,只要被捕获到的自由变量一直使用中,系统就不会回收内存空间!

42410

理解JavaScript的作用

作用域嵌套的查询规则: 首先,JS引擎从当前的执行作用域开始查找变量。 然后,如果找不到,引擎会在外层嵌套的作用域中继续查找。 最后,直到找到该变量,或抵达最外层的全局作用域为止。...function foo(b) { // 变量a全局作用域下查询得到的 console.log(a + b) // 4 } var a = 2 foo(2) 查询异常 如果获取未声明的变量的值会导致...如果对未声明过的变量进行赋值非严格模式下,JS引擎会为其自动创建一个全局变量且进行赋值。 如在严格模式下,会导致 ReferenceError 异常。...函数作用域 函数作用域内的变量或者内部函数,对外都是封闭的,从外层的作用域无法直接访问函数内部的作用域,否则会报引用错误异常。解决方法:闭包。...最外层作用域下使用 var 关键字会定义全局变量,也就是说会挂载 window 对象上,或者不使用关键字 var、let、const 直接对变量名字进行赋值,JS也会自动为其创建为全局变量

68420

python基础—闭包

闭包 自由变量: 未在本地作用域中定义的变量,例如是定义在内层函数外的一个变量 闭包: 就是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包 看一个示例:...内层函数我们的语句块为: c[0] += 1 ,即 c[0] = c[0] + 1 ,这里并没有赋值,而是对外层函数中的一个列表做的一个引用 这里便是闭包,c便是一个自由变量,便是定义在内层函数外的一个变量...,且在内层函数中去引用,而不是重新赋值 而我们即使在外部重新定义了c,但是这个函数调用的却是一个自由变量,外部并不可见 再看一个示例: 这个函数肯定会报错,因为我们对count重新赋值,所以我们可以使用...global将count定义成全局变量便可以解决: 我们如果只是在内层函数里使用global指定好,但是依然会报错,我们还需要在最外层定义一个变量,因为在外部并无该变量存在。...但是如果想让该函数成为闭包,我们可以使用nonlocal来实现 我们这里使用nonlocal标记为不再本地作用域中,而是在上一级局部作用域中定义,但不能是全局作用域中变量

36210

读书笔记-你不知道的JavaScript(上)

编译器会在编译期间执行 var a,然后到作用域中去查找 a 变量,如果 a 变量作用域中还没有声明,那么就在作用域中声明 a 变量,如果 a 变量已经存在,那就忽略 var a 语句。...为什么区分 LHS 和 RHS 是一件重要的事情? 非严格模式下,LHS 调用查找不到变量时会创建一个全局变量,RHS 查找不到变量时会抛出 ReferenceError。...另外即时是具名的函数表达式,名称标识符(这里是 bar )赋值之前也无法在所在作用域中使用。...它的缺陷在于:根据作用域的工作原理,尽管循环中的五个函数是各个迭代中分别定义的,但是它们都被封闭一个共享的全局作用域中,因此实际上只有一个i。因此我们需要更多的闭包作用域。...IIFE 会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用封闭每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问。

970100

深入浅出理解闭包

A作用域中使用的变量x,却没有A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。如下图 image.png 如上程序中,调用fn()函数时,函数体中第6行。...对于本文第一段代码,fn函数中,取自由变量x的值时,要到哪个作用域中取?——要到创建fn函数的那个作用域中取——无论fn函数将在哪里调用。 上面描述的只是跨一步作用域去寻找。...取a的值时,试图fn作用域取,但是取不到,只能转向创建fn的那个作用域中去查找,结果找到了。 这一节看似很轻松的把作用域链引出来,并讲完了。之所有轻松是有几节的基础,否则将很难解释。...函数的特别之处在于可以创建一个独立的作用域.。而正巧合的是,返回的这个函数体中,还有一个自由变量max要引用fn作用域下的fn()上下文环境中的max。...image.png 执行bar(15)时,max是自由变量,需要向创建bar函数的作用域中查找,找到了max的值为10。这个过程作用域链一节已经讲过。

69320

JavaScript 变量提升

本篇博文中,我们一起深入了解这个过程的更多细节。 变量的生命周期 当引擎使用变量时,它们的生命周期包含以下阶段: 声明阶段,这一阶段作用域中注册了一个变量。...初始化阶段, 这一阶段分配了内存并在作用域中让内存与变量建立了一个绑定,变量会被自动初始化为 undefined 。 赋值阶段,这一阶段为已初始化的变量分配具体的一个值。...同时,var variable 函数作用域中的位置并不会影响它的声明和初始化阶段的优先进行。 声明和初始化阶段后,赋值阶段之前,变量的值为 undefined ,且已经可以被使用了。...赋值阶段 varibale = 'some value' ,赋值语句使得变量得到新的赋值。 对于 var ,变量提升指 var 变量的声明阶段和初始化阶段得到提升,并且这两阶段之间没有任何的间隙。...对于 function ,声明、初始化和赋值阶段封闭的函数作用域的开头,便立即执行,其提升优先级比 var 和 let 提升优先级高。

81330

作用域和闭包

,并实施一套非常严格的规则 确定当前执行的代码对这些标识符的访问权限 var a = 2; 变量赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量...换句话说,可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们。 为什么“隐藏”变量和函数是一个有用的技术? 有很多原因促成了这种基于作用域的隐藏方法。...但是根据作用域的工作原理,实际情况是尽管循环中的五个函数是各个迭代中分别定义的,但是它们都被封闭一个共享的全局作用域中 ,因此实际上只有一个 i。...IIFE 会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用封闭每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问。...模块模式需要具备两个必要条件: 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例) 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态

68520

Python 作用域和命名空间

从最近的封闭作用域开始搜索的任何封闭函数的范围包含非局部名称,也包括非全局名称 倒数第二个作用域包含当前模块的全局名称 最外面的范围(最后搜索)是包含内置名称的命名空间 如果一个名称被声明为全局变量,...则所有引用赋值将直接指向包含该模块的全局名称的中间作用域。...如果没有被声明为非本地变量,这些变量将是只读的(尝试写入这样的变量只会在最内层作用域中创建一个 新的 局部变量,而同名的外部变量保持不变)。...删除也是如此:语句 del x 会从局部命名空间的引用中移除对 x 的绑定。 事实上,所有引入新名称的操作都使用局部作用域:特别地,import 语句和函数定义会在局部作用域中绑定模块或函数名称。...global 语句可被用来表明特定变量生存于全局作用域并且应当在其中被重新绑定;nonlocal 语句表明特定变量生存于外层作用域中并且应当在其中被重新绑定。 9.2.1.

68450

JS中的闭包回顾

弄明白函数闭包,先要弄清楚函数执行时的上下文环境。...,由于有变量提升这个机制,所以执行上下文环境中,数据体现的不尽相同: 变量、函数表达示 ———— 变量声明,默认赋值为 undefined this ———— 赋值 函数声明 ———— 赋值 而在函数体环境中...f){ 6 var x = 50; 7 f(); //打印22,而不是50 8} 9fn2(fn) 给执行上下文环境下个通俗的定义:执行代码,把将要用到的所有变量都事先拿出来...这里再补充个自由变量的概念:某个作用域中使用的变量X,却没有作用域中声明(换句话说就是变量X是在其他作用域中声明的),对于该作用域来说,这个变量X就是自由变量。...那么这个自由变量X的取值又该怎么取呢?记住:要到创建这个函数的作用域中去取值,举例如下。

1.3K30

JavaScript之作用域和闭包

本质上,声明一个函数内部的变量或函数会在所处的作用域中“隐藏”起来,即函数内定于的函数和变量为该函数私有; 块级作用域: 块作用域指的是变量和函数不仅可以属于所处的作用域,也可以属于某个代码块(...通常指 { .. } 内部) ES6JavaScript中并不存在块级作用域( 例外:try/catch 结构 catch 分句中具有块作用域); ES6 中引入了 let 关键字( var...第二个赋值声明会被留在原地等待执行阶段。 这个过程就好像变量和函数声明从它们代码中出现的位置被“移动”到了最上面。这个过程就叫作提升。...实际情况是尽管循环中的五个函数是各个迭代中分别定义的,但是它们都被封闭一个共享的全局作用域中,因此实际上只有一个 i,即所有函数共享一个 i 的引用 。...,使得延迟函数的回调可以将新的作用封闭每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问。

67810
领券