闭包也就这玩意

本文通过对比面向对象的方式,解释了JavaScript中闭包的概念,并提供了一个简单的计数器示例来展示闭包如何工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闭包也叫closure这东西听起来挺玄乎,《js犀牛书》上搞了一计数器作为例子,如下:

 

function counter() {
    var n = 0;
    return {
        count: function() { return n++; },
        reset: function() { n = 0; }
    };
}
var c = counter(), d = counter();   // Create two counters
c.count()                           // => 0
d.count()                           // => 0: they count independently
c.reset()                           // reset() and count() methods share state
c.count()                           // => 0: because we reset c
d.count()                           // => 1: d was not reset

 我看了半天,没觉得有啥大不了的,感觉很自然,我转念一想,这不就是把函数当成面向对象中的类了嘛

 

public class counter() {
    private int n = 0;
  
    public int count{ return n++; },
    public void reset{ n = 0; }
}
counter c = new counter();
counter d = new counter();   // Create two counters
c.count()                           // => 0
d.count()                           // => 0: they count independently
c.reset()                           // reset() and count() methods share state
c.count()                           // => 0: because we reset c
d.count()                           // => 1: d was not reset

 肿么样?是这回事吧,其实闭包就是:

“把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value)。”

欢迎拍砖。

 

一个较为详细的关于闭包的文章如下:

深入理解js闭包

05-30
<think>嗯,用户想了解闭包的概念以及它和装饰器的关系。之前我回答过关于装饰器的问题,现在需要结合之前的回答来补充闭包的内容。首先,我得明确闭包的定义,可能要从嵌套函数和变量作用域开始讲起。闭包在Python中是如何形成的?比如,外层函数返回内层函数,内层函数引用了外层函数的变量,这样就形成了闭包。这样闭包可以保存外层函数的状态,对吧?然后要说明闭包的作用,比如数据封装、延迟计算、保持状态等。可能需要举一个计数器的例子,这样用户能直观理解闭包如何保存状态。比如外层函数定义一个计数器变量,内层函数每次调用时增加这个计数器,并返回当前值。这样每次调用闭包函数时,计数器不会被重置。接下来要联系到装饰器。装饰器的本质其实就是一个返回函数的高阶函数,而很多装饰器内部使用了闭包结构。比如之前用户提到的log_time装饰器,里面wrapper函数引用了外层函数log_time的参数func,这就是闭包的应用。通过闭包,装饰器能够记住被装饰的函数,并在调用时执行额外的逻辑。 还要注意闭包和装饰器的区别,闭包是概念,装饰器是应用。装饰器利用闭包来保持装饰函数的状态,比如被装饰的函数、装饰器的参数等。可能需要举一个带参数的装饰器的例子,说明外层函数接收参数,内层装饰器函数使用这些参数,形成闭包,从而在调用时保留这些参数的值。 另外,用户可能想知道闭包在装饰器中的具体应用场景,比如保持装饰器的配置或者多次调用间的状态。比如重试装饰器retry,里面需要记录尝试的次数,闭包可以让wrapper函数访问max_tries这个参数,而不需要全局变量。然后要回答用户的问题,闭包的作用和与装饰器的关联,需要分点说明,结构清晰。可能还需要提到闭包中的变量访问规则,比如nonlocal关键字的使用,防止在Python中因为赋值操作而将变量视为局部变量。最后生成相关问题,可能涉及闭包的变量修改、装饰器中的闭包使用注意事项、闭包与类的区别等。确保问题覆盖用户可能进一步探索的方向。在写作过程中,要使用中文,数学公式用正确的LaTeX格式,比如变量用$variable$,独立公式用$$...$$。引用之前回答中的例子时,加上引用标识,比如[^1]。同时检查是否有遗漏的点,比如闭包的内存管理问题,或者装饰器叠加时的闭包情况,但可能不需要深入,保持回答简洁明了。</think>### 闭包的概念与作用 **闭包(Closure)** 是函数与其相关引用环境(即外层作用域中的变量)的组合体。当一个嵌套函数引用了外层函数的变量,且外层函数返回内层函数时,就形成了闭包。其核心作用是**保持状态**和**实现数据封装**。 #### 闭包的关键特征 1. **嵌套函数结构**:内层函数定义在外层函数内 2. **变量引用**:内层函数引用外层函数的变量 3. **返回函数对象**:外层函数返回内层函数作为返回值 ```python def outer_func(x): def inner_func(y): return x + y # 引用外层函数的变量x return inner_func # 返回闭包 closure = outer_func(10) print(closure(5)) # 输出15(保留x=10的状态) ``` ### 闭包与装饰器的关系 装饰器的本质是通过闭包实现的**高阶函数**应用。装饰器函数接收被装饰函数作为参数,在闭包中实现功能扩展,最后返回新的函数对象[^1]。 #### 典型装饰器的闭包结构 ```python def decorator(func): # 外层函数接收参数 def wrapper(*args): # 闭包函数 print("前置操作") # 扩展功能 result = func(*args) # 调用原函数(闭包保留func引用) print("后置操作") return result return wrapper # 返回闭包 @decorator def my_func(n): return n * 2 ``` ### 闭包在编程中的核心作用 | 作用类型 | 说明 | 数学表达示例 | |----------------|--------------------------------------|-------------------------------| | 状态保持 | 保存外层函数变量的最终状态 | 计数器:$f(x) = x + \Delta$ | | 延迟计算 | 捕获变量值但不立即执行 | 惰性求值:$g(x) = \int f(x)dx$| | 配置封装 | 将参数与环境绑定 | 参数化函数:$h(a)(x) = a \cdot x$ | #### 示例:闭包实现计数器 ```python def counter(): count = 0 # 外层变量 def increment(): nonlocal count # 声明非局部变量 count += 1 return count return increment c = counter() print(c(), c(), c()) # 输出1,2,3(保持count状态) ``` ### 闭包与装饰器的交互原理 1. **参数传递**:装饰器参数通过外层函数捕获,形成闭包环境 2. **函数替换**:装饰后的函数实际调用的是闭包函数`wrapper` 3. **状态隔离**:每个被装饰函数都会创建独立的闭包环境 #### 带参数装饰器的闭包结构 ```python def retry(max_attempts): # 外层获取装饰器参数 def decorator(func): # 中间层接收被装饰函数 def wrapper(*args): # 闭包函数 for _ in range(max_attempts): try: return func(*args) except Exception: pass raise RuntimeError return wrapper return decorator @retry(max_attempts=3) # 创建闭包保存max_attempts=3 def fetch_data(): # 数据获取逻辑 ``` ### 闭包的特殊注意事项 1. **变量捕获时机**:闭包捕获的是变量的引用,而非当前值 ```python funcs = [] for i in range(3): def wrapper(): return i # 所有闭包最终都捕获i=2 funcs.append(wrapper) print([f() for f in funcs]) # 输出[2,2,2] ``` 2. **内存泄漏风险**:长期存在的闭包可能阻止垃圾回收 3. **nonlocal声明**:在Python中修改外层变量需要`nonlocal`关键字
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值