Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day8 - 什么是闭包?如何产生闭包 #20

Open
su37josephxia opened this issue Jan 5, 2022 · 36 comments
Open

Day8 - 什么是闭包?如何产生闭包 #20

su37josephxia opened this issue Jan 5, 2022 · 36 comments

Comments

@su37josephxia
Copy link
Owner

su37josephxia commented Jan 5, 2022

@JanusJiang1
Copy link

什么是闭包?
当一个嵌套的内部函数引用了嵌套的外部函数的变量,函数时,就产生了闭包。
比如:

function a(){
   var c=1;
  return function b(){
       c+=1
      console.log(c)
   }
}

var n=a();
n( ); //2
n( ); //3

就是一个简单的闭包,全局作用域中函数a中返回函数b,并声明了变量c,再通过n=a(),n()的方式去调用b。
那这样做和直接把,c,b定义到全局,然后值=直接调用b()有什么区别呢?

  1. 这样比起直接在全局中声明b,c,避免了b,c变量直接被声明到全局环境中,而是把他们现在在了a的函数作用域中。在实际开发中就能起到防止全局作用域污染的作用。
  2. 连续调用两次n(),结果再递增,说明c变量一直没被销毁,一直在内存中常驻,只要n不销毁,就一直在内存中,这样也实现了和把变量一直放到全局的效果,又起到了作用域隔离的效果。

所以,闭包是一种形式,内部函数可以访问其所在的外部函数中声明的参数和变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!

@crazyyoung1020
Copy link

crazyyoung1020 commented Jan 8, 2022

什么是闭包?

闭包是指那些引用了另一个函数作用域中变量的函数。
参见红宝书309页。

闭包的缺点:使用不当,容易导致内存泄漏。因为闭包会保存对父函数活动对象的引用,所以父函数执行结束,虽然他执行上下文的作用域链会销毁,但它的活动对象会保留在内存当中。

闭包的优点:

  1. 可以封装函数内的私有变量,仅供函数内的闭包使用,此时闭包就相当于函数内和函数外的桥梁,同时可以访问两者的活动对象,对于此时的闭包函数来说,它的私有变量处在作用域链的最顶端,然后是定义它的函数上下文的作用域。
  2. 让父函数中的变量始终保存在内存中。

如何产生闭包?

在函数内部定义函数,并return出去

@QbjGKNick
Copy link

闭包的定义
函数执行形成一个私有的上下文,此上下文中的私有变量和上下文以外的变量互不干扰,也就是当前上下文把这些变量保护起来了,这种函数保护机制称之为闭包。
闭包的优缺点
优点:对私有变量进行保护和保存
缺点:如果使用不当会造成内存泄漏
闭包的应用
函数的防抖和节流以及柯里化函数、compose组合函数等都应用到了闭包。

@Cassieqian
Copy link

函数及函数能访问到的变量组成了闭包。

@oujinlong
Copy link

闭包是 “函数” 和 “函数能访问到的变量” 的总和成为闭包。一般嵌套在函数内达到隐藏变量的目的

@su37josephxia su37josephxia changed the title 什么是闭包? 什么是闭包?如何产生闭包 Jan 8, 2022
@wzl624
Copy link

wzl624 commented Jan 8, 2022

  • 定义:当一个函数嵌套在另一个函数中且引用了其父函数中的变量,此时内嵌的函数就形成了闭包。
  • 特点:被闭包引用的变量在外层函数执行结束后不会被销毁,而是保存在内存中,再次调用会以上次执行结束的值作为再次调用的初始值。
  • 用处:函数柯里化,防抖和节流等
  • 缺点:使用不当会造成内存泄漏。

@chunhuigao
Copy link

JavaScript高级编程第4版中这样介绍闭包:

  • 闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的;
  • 因为闭包会保留它们包含函数的作用域,所以比其他函数更占用内存。过度使用闭包可能导致内存过度占用,所以要慎重使用闭包
  • 保护私有变量
  • 容易引起内存泄漏

@BambooSword
Copy link

闭包指的是那些引用了另一个函数作用域中变量的函数。比如我们创建了一个函数A,函数里面又创建了一个函数B,此时就存在三个作用域:
全局作用域、A作用域、B作用域,即是全局作用域包含了A作用域,A作用域包含了B作用域。
当B在查找变量的时候会先从自身的作用域区查找,找不到再到上一级A的作用域查找,如果还没找到就到全局作用域查找,这样就形成了作用域链。
当一个函数被执行完后,其作用域会被回收,如果形成了闭包,执行完后其作用域就不会被回收。

闭包的作用

  • 保存自己私有变量,通过提供接口给外部使用,但外部不能直接访问该变量。
  • 使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收

@674252256
Copy link

闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的

  • 函数内部的代码在访问变量时,就会使用给定的名称从作用域链中查找变量。
  • 函数执行完毕后,局部活动对象会被销毁,内存中就只剩下全局作用域
  • 闭包-在一个函数内部定义的函数会把其包含函数的活动对象添加到自己的作用域链中

@rachern
Copy link

rachern commented Jan 8, 2022

什么是闭包?

当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包。

如何产生闭包

function foo() {
    var a = 2
    function bar() {
        console.log(a)
    }
    return bar
}
foo()()

以上函数,内部的 bar 访问了外部 foo 作用域中的变量,当其被调用时,就产生了闭包

@792472461
Copy link

当一个函数能够记住并访问它所在的词法作用域的时候,就产生了闭包,即使函数是在词法作用域之外执行

闭包的集中形式

  1. 返回一个函数
  2. 作为函数参数传递
  3. 回调函数
  4. 非典型闭包IIFE(立即执行函数表达式)

返回一个函数:这种形式的闭包在JavaScript的代码编写中,是非常常见的一种方式。

var a  = 1;
function foo(){
  var a = 2;
  // 这就是闭包
  return function(){
    console.log(a);
  }
}
var bar = foo();
// 输出2,而不是1
bar();

作为函数参数传递:无论通过何种手段将内部函数传递到它所在词法作用域之外,它都会持有对原始作用域的引用,无论在何处执行这个函数,都会产生闭包。

var a = 1;
function foo(){
  var a = 2;
  function baz(){
    console.log(a);
  }
  bar(baz);
}
function bar(fn){
  // 这就是闭包
  fn();
}
// 输出2,而不是1
foo();

回调函数:在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就是在使用闭包。

// 定时器
setTimeout(function timeHandler(){
  console.log('timer');
},100)

// 事件监听
$('#container').click(function(){
  console.log('DOM Listener');
})

IIFE:IIFE(立即执行函数表达式)并不是一个典型的闭包,但它确实创建了一个闭包。

var a = 2;
(function IIFE(){
  // 输出2
  console.log(a);
})();

@yaoqq632319345
Copy link

定义:闭包指的是那些引用了另一个函数作用域中变量的函数,
产生:一般通过一个函数返回另一个函数,当被返回的函数被调用时就可以访问之前函数的作用域从而形成闭包
特点:通常一个函数执行完之后,会回收函数的执行上下文,但是由于有另外一个函数引用了当前函数内部的变量,所以这些被引用的变量不会被回收,
优缺点:利用这个特点可以使内部变量可以被外界访问到,但是需要注意大量使用闭包会产生许多不被回收的变量,导致占用过多内存

@qytayh
Copy link

qytayh commented Jan 8, 2022

什么是闭包

闭包指的是那些引用了另一个函数作用域中变量的函数。

如何产生

在js中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之回收,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数——也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后作用域内的值也不会被销毁

@zzzz-bang
Copy link

什么是闭包
一个闭包是一个可以自己拥有独立的环境与变量的表达式。本质就是在一个函数内部创建另一个函数
如何产生闭包
当内部函数以某一种方式被任何一个外部函数作用域访问时,一个闭包就产生了
闭包可以用在许多地方。它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,

@zcma11
Copy link

zcma11 commented Jan 8, 2022

闭包是保存在函数内的对外部函数作用域变量的引用。当一个函数内的函数引用了外部函数作用域的变量时,闭包就产生了。它可以让这个函数在它的外部作用域被销毁,无法顺着作用域链查找这个变量的时候依然能读到这个变量的值。但因为变量依然被引用,所以使用不当会造成内存泄漏。

@bianzheCN
Copy link

闭包

引用了外部函数变量的一个函数

产生闭包

当一个函数保持了对外部函数变量的引用,我们就称产生闭包

@Colin3191
Copy link

内层函数对外层函数变量引用的集合就是闭包,闭包可以让一个内层函数访问到其外层函数的作用域。

@liangle
Copy link

liangle commented Jan 8, 2022

根据闭包金典定义,闭包包含了:

  • 环境部分
    • 环境:函数的词法环境(执行上下文的一部分)
    • 标识符列表:函数中用到的未声明的变量
  • 表达式部分:函数体

我们可以认为,JS 中的函数完全符合闭包的定义。它的环境部分是函数词法环境,它的标识符列表是函数中用到的未声明变量,它的表达式部分就是函数体。

JS 中的每个函数都会产生闭包。

@partiallove
Copy link

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

产生一个闭包
创建闭包最常见方式,就是在一个函数内部创建另一个函数。下面例子中的 closure 就是一个闭包:
`function func(){
var a = 1,b = 2;

function closure(){
return a+b;
}
return closure;
}`

@rhythm022
Copy link

闭包是有一个定义的,就是说一个函数,你不仅可以在他内部访问他本地声明的数据,你还可以访问非本地声明的数据(比如说外部的词法环境里的数据),那么他这样的一个函数就是一个闭包了。

所以在JS中,你只要在函数体里面去引用外部的变量,或外部的函数,那么,它都是相当于产生了一个闭包。

PS:所谓的词法环境,它里面存放的都是声明,包括了函数声明,变量声明这些东西。

@jiafei-cat
Copy link

什么是闭包

为了保证父级函数(script也是)在执行栈内被销毁,它的执行上下文也会被销毁,为了保证子函数还能够访问父级函数上下文的一种缓存,V8会根据子函数的引用标记出哪些是子函数所需要的上下文,这就是闭包和闭包的作用

可以说每个使用了外部执行上下文(上层作用域)的函数都有Closure

那么闭包什么时候产生的

父级函数在执行销毁的时候,声明子函数会根据父级函数执行上下文(作用域链)生成在子函数对象Scopes.Closure上,并存储在堆空间的中

@8023nana
Copy link

8023nana commented Jan 8, 2022

闭包就是指有权访问另一个函数作用域中的变量的函数。
闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。
创建闭包最常见方式,就是在一个函数内部创建另一个函数
假如当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

@ruixue0702
Copy link

一个函数的内部可以获取到另一个函数内部的变量或者方法,就会形成一个闭包;比如,在嵌套函数中,内部函数可以读取到外部函数内定义的变量,这就是一个闭包;闭包比较消耗内存,过度使用闭包也会造成内存的泄漏,因此在实际的代码中要谨慎使用闭包;

@yl-code
Copy link

yl-code commented Jan 8, 2022

@attackam
Copy link

attackam commented Jan 8, 2022

闭包就是能够读取其他函数内部变量的函数。

只要在函数A内部写一个函数B,在函数B中引用一下函数A的变量就形成了闭包。

关于闭包的使用场景和优缺点下到题目再答。欲知后事如何请听下回分解。

@yanzefeng
Copy link

yanzefeng commented Jan 8, 2022

什么是闭包

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

形成闭包

闭包就是函数嵌套函数,内部函数引用了外部函数的变量,这样就形成了一个闭包

@Limeijuan
Copy link

闭包就是那种可以引用另一个函数作用域变量的函数,通常是在嵌套函数中实现;
它的特点就是可以延长外部函数的作用域,
通常情况下,函数执行完成后,它内部的所有活动对象、作用域链都会被销毁;
但是闭包函数会延长它外部函数的活动对象(定义的各种变量),如果闭包函数一直没执行那么它外部函数的活动对象就一直得不到释放,一直占用内存。所以实际应用中要小心用闭包,避免内存占用过度。

@alec1815
Copy link

alec1815 commented Jan 8, 2022

只要变量或函数存在于声明函数时的作用域内,闭包即可使函数能够访问这些变量或函数。-- javascript忍者秘籍第2版

@MMmaXingXing
Copy link

MMmaXingXing commented Jan 8, 2022

闭包:有权访问另一个函数作用域中的变量的函数

创建闭包的常见方式,通常是在一个函数内部创建另一个函数

也可以创建一个全局对象然后在函数中引用对象

当某个函数被调用时,会创建一个执行环境以及相应的作用域链。然后使用arguments和其他命名参数的值来初始化函数的活动对象。闭包会携带包含它的函数的作用域。

@Theseus-Xin
Copy link

闭包其实只是一个绑定了执行环境的函数,这个函数并不是印在书本里的一条简单的表达式,闭包与普通函数的区别是,它携带了执行的环境,就像人在外星中需要自带吸氧的装备一样,这个函数也带有在程序中生存的环境。
古典的闭包定义中,闭包包含两个部分。

  • 环境部分

    • 环境
    • 标识符列表
  • 表达式部分
    在 JavaScript 中找到对应的闭包组成部分。

  • 环境部分

    • 环境:函数的词法环境(执行上下文的一部分)
    • 标识符列表:函数中用到的未声明的变量
    • 表达式部分:函数体

@superjunjin
Copy link

什么是闭包

闭包让你可以在一个内层函数中访问到其外层函数的作用域。

如何产生闭包

每当创建一个函数,闭包就会在函数创建的同时被创建出来。

@alienRidingCat
Copy link

一个函数可以访问它被创建时的上下文环境被称为闭包。因此,在一个函数在被创建时,闭包就已经产生,它允许函数访问局部作用域之外的数据。但是过度的使用闭包这一特性,可能会产生一些副作用,因为通常情况下,函数的活动对象会随着执行环境一同销毁,但是如果使用了闭包,函数中所激活使用的对象无法被销毁,过多使用可能会造成内存泄漏。

@jj56313751
Copy link

  • 闭包是指一个函数内部能使用函数外定义的变量
  • 定义一个全局变量,再定义一个函数,函数其内部引用这个全局变量就生成了一个闭包

@bubucuo
Copy link

bubucuo commented Jan 8, 2022

js使用词法作用域,函数对象与作用域组合起来解析函数变量的机制,叫闭包,俗称包养变量。

@aiuluna
Copy link

aiuluna commented Jan 8, 2022

  • 闭包是指有权访问另一个函数作用域中的变量的函数
  • 通常情况下是可以通过在一个函数中定义另一个函数形成闭包,其实只要定义了函数,函数访问了上级或者上上级作用域中的变量就形成闭包

@zhenyuWang
Copy link

什么是闭包?

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

如何产生闭包?

在一个函数内部创建另一个函数,并且内部函数访问外部函数中的变量。

@su37josephxia su37josephxia changed the title 什么是闭包?如何产生闭包 Day8 - 什么是闭包?如何产生闭包 Jan 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests