看完这个不懂闭包,准备铺盖走人

您所在的位置:网站首页 js匿名函数的作用域 看完这个不懂闭包,准备铺盖走人

看完这个不懂闭包,准备铺盖走人

2023-05-22 06:22| 来源: 网络整理| 查看: 265

在本文中,我们将详细讲解 JavaScript 闭包的概念、原理和应用。闭包是 JavaScript 中一个非常重要的概念,理解闭包对于编写高效、可维护的代码至关重要。

什么是闭包?

闭包(Closure)是指一个函数可以访问并操作其外部作用域中的变量。换句话说,闭包使得一个函数可以“记住”它所在的词法环境,即使该函数在其原始词法环境之外执行。在 JavaScript 中,闭包通常由一个函数和一个函数所在的作用域对象组成。当函数被创建时,它会创建一个闭包,并将其与当前的作用域对象绑定在一起。在函数执行期间,闭包会持续存在,即使函数执行完毕,它也仍然存在。这就允许函数访问并操作其创建时所在的作用域对象中的变量。

闭包的原理

JavaScript 采用词法作用域(lexical scoping),也就是说,函数的作用域在函数定义时就已经确定。当一个函数嵌套在另一个函数内部时,内部函数可以访问外部函数的变量。这种能力就是闭包。

闭包的原理可以归结为以下两点:

函数可以作为参数或返回值传递。

函数可以访问其外部作用域的变量。

闭包的应用

闭包在 JavaScript 中有很多应用场景,以下是一些常见的例子:

模块化:通过闭包,我们可以创建私有变量和方法,从而实现模块化。这有助于保护内部实现细节,避免全局变量污染。

function createCounter() {   let count = 0;   return {     increment: function () {       count++;     },     getCount: function () {       return count;     },   }; } const counter = createCounter(); counter.increment(); console.log(counter.getCount()); // 输出 1

上面的例子中,我们不用关注count的具体实现逻辑,我们通过调用方法来获取count的值,外部无法直接操作count,从而对count起到了保护作用。

事件处理:闭包可以用于在事件处理程序中保存状态信息。

function createButton(text) {   const button = document.createElement("button");   button.textContent = text;   let clickCount = 0;   button.addEventListener("click", function () {     clickCount++;     console.log(`${text} button clicked ${clickCount} times.`);   });   return button; } document.body.appendChild(createButton("Click me!"));

函数柯里化(Currying):闭包可以用于实现函数柯里化,将多参数函数转换为一系列单参数函数。

function curry(fn) {   const arity = fn.length;   return function curried(...args) {     if (args.length >= arity) {       return fn.apply(this, args);     } else {       return function (...moreArgs) {         return curried.apply(this, args.concat(moreArgs));       };     }   }; } function add(a, b, c) {   return a + b + c; } const curriedAdd = curry(add); console.log(curriedAdd(1)(2)(3)); // 输出 6

上例中,fn.length能得出一个函数的参数个数。当你传入的参数小于原函数参数个数时,会把参数concat起来并返回curried函数给你让你可以接着调用,直到你的参数大于等于原函数参数个数时,才调用原函数。

延迟执行:通过闭包来延迟执行函数,可以优化代码性能,避免在短时间内频繁执行同一个函数

function debounce(fn, delay) {   var timeoutId;   return function() {     var context = this;     var args = arguments;     clearTimeout(timeoutId);     timeoutId = setTimeout(function() {       fn.apply(context, args);     }, delay);   }; } function doSomething() {   console.log('Doing something...'); } var debouncedDoSomething = debounce(doSomething, 1000); debouncedDoSomething(); // 在1000ms后输出 "Doing something..." debouncedDoSomething(); // 取消前一个定时器并在1000ms后输出 "Doing something..."

上面的例子就是一个经典的防抖函数。我们定义了一个 debounce 函数,该函数接受一个函数和延迟时间作为参数,并返回一个闭包。在闭包内部,我们使用 setTimeout 延迟执行函数,并使用 clearTimeout 取消前一个定时器,从而避免在短时间内频繁执行同一个函数。使用闭包来实现防抖可以避免在短时间内频繁执行同一个函数,从而提高代码的性能和响应速度。需要注意的是,使用防抖时,需要合理设置延迟时间,避免影响用户体验。

缓存数据:通过闭包来缓存数据,可以避免重复计算,提高代码性能

function fibonacci() {   var cache = {};   function fib(n) {     if (n 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3