闭包速记

闭包速记

什么是闭包?

谈到闭包,很多人总是会对闭包的概念比较模糊,简单来说如下:

  • 闭包就是能够读取其他函数内部变量的函数
  • 闭包是指有权能够访问另外一个函数作用域中变量的函数 ,创建闭包的最常见方式就是在一个函数内部创建另一个函数,通过另外一个函数访问这个函数的局部变量,利用闭包可以突破作用域链。

闭包的特性如下:

  • 函数内再嵌套函数;
  • 内部函数可以引用外层的参数和变量;
  • 参数和变量不会被垃圾回收机制回收;

谈一下对闭包的理解?

  • 使用闭包主要是为了设计私有化的方法和变量 。闭包的优点可以避免全局变量的污染 ,缺点是闭包会常驻内存,会增大内存的使用量 ,使用不当很容易造成内存泄漏。在js中,函数即闭包,只有函数才会产生作用域的概念。
  • 闭包的最大用处有两个,一个是可以读取函数内部的变量 ,另外一个就是让这些变量始终保存在内存中
  • 闭包的另外一个好处就是封装对象的私有属性和私有方法
  • 使用闭包的好处就是实现封装和缓存 ,坏处就是消耗内存,不正当使用会造成内存溢出问题。

使用闭包注意项:

  • 由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能会导致内存泄漏。
  • 如何解决呢:就是在退出函数之前,将不使用的变量全部清除

闭包的应用:

闭包在Javascript 中非常常见,它允许函数访问和操作函数外部的变量。最常见的应用之一是创建私有变量和私有方法。

例如:我们可以使用闭包来创建一个计时器:

js 复制代码
/**
 * 闭包实现计时器
 */

function createCounter() {
    let count = 0;

    return {
        increment() {
            count++;
        },
        getCurrentCount() {
            return count;
        }
    }
}

const counter = createCounter();
counter.increment();
console.log(counter.getCurrentCount()); //输出1

上述例子中,createCounter函数返回了一个对象,该对象有两个方法:incrementgetCurrentCount。这两个方法都可以访问和操作createCounter函数内部的私有变量count。由于createCounter函数的执行上下文(包括其变量对象)在返回的对象方法被调用时依然存在,因此这些方法形成了一个闭包,可以访问和操作count

使用闭包造成内存泄漏如何解决:

当闭包引入了一个外部函数的变量,并且这个闭包被长期保存 (例如被赋值给一个全局变量或者被加入到一个长期存在的数据结构中),那么外部函数的执行上下文(包括变量对象)就不能被垃圾收集器回收 ,即使外部函数本身已经不需要了。这种情况可能会导致内存泄漏

js 复制代码
function createLeakyCounter() {
    let count = 0;

    return {
        increment: function () {
            count++;
        }
    }
}

// 将闭包赋值给一个全局变量
window.leakyCounter = createLeakyCounter();

// 假设其他代码在后续的执行过程中不断调用 leakyCounter.increment()

上述例子中,createLeakyCounter函数返回了一个只有increment方法的对象。这个对象被赋值给了全局变量leakyCounter,因此它不会被垃圾收集器回收。而leakyCounter又引用了createLeakyCounter函数内部的变量count,导致createLeakyCounter的执行上下文也不能被回收。即使createLeakyCounter函数本身不再需要,它的执行上下文仍然会占据内存,造成内存泄漏。

解决方法:解决由闭包引起的内存泄漏的一种常见的方法是解除不必要的引用。

在上述例子中我们可以将leakyCounter设为null来解除对createLeakyCounter执行上下文的引用。当没有其他代码再引用leakyCounter时,它的执行上下文就可以被垃圾收集器回收了,从而避免了内存泄漏。

js 复制代码
window.leakyCounter = null;
相关推荐
yqcoder18 分钟前
NPM 包管理问题汇总
前端·npm·node.js
程序菜鸟营24 分钟前
nvm安装详细教程(安装nvm、node、npm、cnpm、yarn及环境变量配置)
前端·npm·node.js
bsr198335 分钟前
前端路由的hash模式和history模式
前端·history·hash·路由模式
杨过姑父1 小时前
ES6 简单练习笔记--变量申明
前端·笔记·es6
2401_897916841 小时前
2018 秋招 百度二轮面试---血淋淋的经历写实
面试·职场和发展
Jacob程序员1 小时前
leaflet绘制室内平面图
android·开发语言·javascript
Sunny_lxm1 小时前
<keep-alive> <component ></component> </keep-alive>缓存的组件实现组件,实现组件切换时每次都执行指定方法
前端·缓存·component·active
eguid_11 小时前
JavaScript图像处理,常用图像边缘检测算法简单介绍说明
javascript·图像处理·算法·计算机视觉
sunly_2 小时前
Flutter:自定义Tab切换,订单列表页tab,tab吸顶
开发语言·javascript·flutter
咔咔库奇2 小时前
【TypeScript】命名空间、模块、声明文件
前端·javascript·typescript