闭包--备忘

本文深入探讨了闭包的概念及其在JavaScript中的应用,详细介绍了闭包如何让内部函数访问外部作用域,并通过实例展示了防抖(debounce)和节流(throttle)技术的实现方法。

概念

函数和对其周围状态的引用捆绑在一起构成了闭包

周围状态,也就是词法环境。
闭包,可以让内部函数访问外部作用域,在Javascript中,每当函数被创建,就会在函数生产时生成闭包。

闭包的一些应用

闭包的使用的一些场景,柯里化,节流,防抖

最简单的一个节流

    function throttle(fn,times){   // 整个throttle为周围状态,或者词法环境
      let t1 = true   // 相对return 的函数就是外部
      return function(){
        if(!t1){   // 内部使用
          return false;
        }
        t1 = false
       let time = setInterval(()=>{
          fn.apply(this)
          t1 = false
        },times)
      }
    }

最简单的一个柯里化

function carling(fn,...args){ 
      let length = fn.length  //判断当前传入函数的长度
      return function (...nextArgs){
        var allArgs = [...args, ...nextArgs]
        if(nextArgs.length == 0){  // 当没有参数的时候我们执行传进来的函数
          return fn.apply(fn,allArgs)
        }
        return carling(fn,...allArgs) 
      }
    }

简单的节流

function debounce(fn,delay){
	let timer = null
	return function (){
		if(timer){
		  clearTimeOut(timer)
		  timer = setTimeOut(fn,delay)
		}else{
		  timer = setTimeOut(fn,delay)
		}
	}
}

PS.说是闭包,其实我是来回顾防抖节流的,下次一定!!

### 闭包的实际应用场景 #### 1. 数据封装与隐私保护 闭包允许开发者在函数内部定义私有变量,从而实现数据的封装。这种特性使得外部无法直接访问某些敏感的数据或逻辑,仅可以通过特定的方法来操作它们。 ```javascript function createCounter() { let count = 0; // 私有变量 return { increment: function () { count++; }, // 修改计数器 get: function () { return count; } // 获取当前值 }; } const counter = createCounter(); counter.increment(); // 调用方法修改count console.log(counter.get()); // 输出1 [^1] ``` 此代码展示了如何利用闭包隐藏`count`变量,并提供受控接口对其进行增减操作。 #### 2. 函数工厂模式 通过返回不同的函数,可以根据传入参数动态生成具有不同行为的新函数。这种方式常用于配置初始化或者构建一系列相似功能但略有差异的操作工具集。 ```javascript function multiplier(factor) { return function (value) { return value * factor; }; } let doubleIt = multiplier(2); console.log(doubleIt(5)); // 结果为10 [^3] ``` 在此例子中,`multiplier`作为高阶函数接受一个乘法因子factor, 并返回一个新的匿名函数完成具体的数值计算工作. #### 3. 延迟求值与事件处理程序绑定 当需要延迟执行某段代码直到某个条件满足时(比如点击按钮触发动作),可以借助闭包保存状态直至适当时候再调用关联的功能模块。 ```javascript for(var i=0;i<5;i++) { setTimeout(function(){ console.log(i); },i*1000); } // 上述代码会打印五次'5', 若要得到期望的结果即依次递增,则需调整如下: for(let j=0;j<5;j++) { setTimeout(() => { console.log(j); },j*1000); } // 或者使用立即执行函数表达式(IIFE) for(var k=0;k<5;k++) { (function(k){ setTimeout(function(){console.log(k)},k*1000); })(k); } ``` 以上片段解释了为什么原始版本会出现问题以及修正后的解决方案之一是如何运用IIFE保持每次循环迭代独立性的良好做法.[^4] #### 4. 高效缓存机制设计 为了提升性能表现,在面对重复运算请求的时候,我们可以采用记忆化技术存储已知答案以便后续快速检索而无需重新计算整个过程。 ```javascript var fibonacciMemoizer = (()=>{ const memo={}; var fib=(num)=>{ if(memo[num]!=undefined)return memo[num]; if(num<=1)memo[num]=num; else{ memo[num]=(fib(num-1)+fib(num-2)); } return memo[num]; }; return fib; })(); console.log(fibonacciMemoizer(7));//输出结果应为13 [^1] ``` 该示例演示了一个简单的斐波那契序列计算器,其中引入了备忘录对象memo储存已经解决过的子问题解,避免不必要的冗余劳动。 --- ### Python中的闭包应用案例 虽然本文主要围绕JavaScript展开讨论,但在Python里同样存在丰富的关于闭包的应用场景。例如下面展示了一种常见的误解情况下的修复办法: ```python def generate_functions(): functions_list = [] for i in range(3): def func(x=i): # 这里的默认参数x绑定了当时的i值而不是最终结束时的状态. print(x) functions_list.append(func) return functions_list funcs = generate_functions() for f in funcs: f() # 正确输出应该是分别显示数字0至2而非三个相同的最后更新值2。 ``` 上述脚本纠正了之前提到的那个常见陷阱——由于缺乏对闭包特性的正确认识而导致的行为异常现象。[^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值