【JS】理解闭包及其应用

历史小剧场

明朝灭亡,并非是简单的政治问题,事实上,这是世界经济史上的一个重要案例。
所谓没钱,就是没有白银。----《明朝那些事儿》

什么是闭包?

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

闭包变量存储位置?

  • 堆内存

假如闭包中的变量存储在栈内存中,那么栈的回收,会把处于栈顶的变量自动回收。所以闭包中的变量如果处于栈中那么变量被销毁后,闭包中的变量就没有了。所以闭包中的变量是处于堆内存中的。

闭包的作用?

  • 创造私有变量,且延长私有变量的生命周期

应用

  1. 延伸函数生命周期
function hd() {
    let n = 1;
    return function sum() {
       console.log(++n)
    }
    sum()
}
let a = hd();
a(); // 2
a(); // 3
a(); // 4
a(); // 5
a(); // 6
let b = hd()
b() // 2
b() //3
let c = hd()
c() // 2

console.log("---------- 用完就删 --------")
function hd2() {
    let n = 1;
    function sum() {
       console.log(++n)
    }
    sum()
}
hd2()   // 2
hd2()   // 2
hd2()   // 2


console.log("-------------------------------")
const hd3 = () => {
    let n = 1;
    return () => {
        const m = () => console.log(++n)
        m()
    }
}
hd3()() // 2
hd3()() // 2


console.log("-------------------------------")
const hd4 = () => {
    let n = 1;
    return () => {
        return () => console.log(++n)
    }
}
const h4 = hd4()()
h4();   // 2
h4();   // 3
h4();   // 4
  1. var/let 在for循环中的执行原理
for (var i = 1; i <= 3; i++) {
    console.log(`for里面:${i}`)
}
console.log(`for外面:${i}`) // 4


for (let j = 1; j <= 3; j++) {
    console.log(`for里面: ${j}`)
}
// console.log(`for外面: ${j}`) // ReferenceError: j is not defined


console.log("------------------------------")
for (var k = 1; k <= 3; k++) {
    setTimeout(() => {
        console.log(`var timeout for里面: ${k}`)    // 4 4 4
    }, 1000)
}

console.log("-------------------------------")
for (let l = 1; l <= 3; l++) {
    setTimeout(() => {
        console.log(`let timeout for里面: ${l}`)    // 1 2 3
    }, 1000)
}
  1. 多层作用域嵌套
let arr1 = [];
for (let i = 1; i <= 3; i++) {
    arr1.push(() => i)
}
console.log(arr1[0]()); // 1
console.log(arr1[1]()); // 2
console.log(arr1[2]()); // 3


console.log("----------------------")
let arr2 = [];
for (var i = 1; i <= 3; i++) {
    arr2.push(() => i)
}
console.log(arr2[0]()) // 4
console.log(arr2[1]()) // 4
console.log(arr2[2]()) // 4

console.log("------------------")
let arr3 = [];
for (var i = 1; i <= 3; i++) {
    ((i) => arr3.push(() => i))(i)
}
console.log(arr3[0]()) // 1
console.log(arr3[1]()) // 2
console.log(arr3[2]()) // 3
  1. 获取商品区间以及商品排序

商品区间

const goods = [
    {
        title: "A",
        price: 30,
    },
    {
        title: "B",
        price: 10,
    },
    {
        title: "C",
        price: 50,
    },
    {
        title: "D",
        price: 20,
    },
    {
        title: "E",
        price: 40,
    },
    {
        title: "F",
        price: 60,
    },
    {
        title: "G",
        price: 300,
    },
    {
        title: "H",
        price: 80,
    },
    {
        title: "I",
        price: 20,
    },
    {
        title: "J",
        price: 200
    }
]
console.log("---------------- 商品区间 -----------------")
const getPriceRange = (begin, end) => (val) => val.price >= begin && val.price <= end;
console.table(goods.filter(getPriceRange(20, 50))); // [ { title: 'B', price: 10 }, { title: 'D', price: 20 }, { title: 'E', price: 40 }, { title: 'F', price: 60 }, { title: 'I', price: 20 } ]
console.table(goods.filter(getPriceRange(40, 200))); 

运行结果:
在这里插入图片描述

商品排序

const sortGoods = (key, order = "asc") => (a, b) => order === "asc"? a[key] - b[key] : b[key] - a[key];
console.table(goods.sort(sortGoods("price"))); // [ { title: 'B', price: 10 }, { title: 'D', price: 20 }, { title: 'E', price: 40 }, { title: 'F', price: 60 }, { title: 'I', price: 20 }, { title: 'A', price: 30 }, { title: 'C', price: 50 }, { title: 'H', price: 80 }, { title: 'J', price: 200 }, { title: 'G', price: 300 } ]
console.table(goods.sort(sortGoods("price", "desc"))); 

运行结果:
在这里插入图片描述
5. 移动动画的闭包使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            position: relative;
        }
        button {
            position: absolute;
        }
    </style>
</head>
<body>
    <!-- <button>你好</button> -->
    <button>真好</button>
    <script>
        const btns = document.querySelectorAll('button');
        // btns.forEach((btn) => {
        //     // parent
        //     let left = 1;
        //     btn.addEventListener('click', () => {
        //         setInterval(() => {
        //             console.log(left)
        //             btn.style.left = `${left++}px`;
        //         }, 100) // 会抖动
        //     })
        // })

        btns.forEach(btn => {
            let bind = false;
            btn.addEventListener('click', () => {
                if (!bind) {
                    let left = 1;
                    bind = setInterval(() => {
                        console.log(left)
                        btn.style.left = `${left++}px`;
                    }, 100)  // 不会抖动
                }
            })
        })
    </script>
</body>
</html>
  1. 实现缓存模拟localStorage
  • 可以通过set方法存值,get方法取值
const myStorage = (function () {
    const cache = {}
    return {
        set: (key, val) => {
            cache[key] = val
        },
        get: (key) => {
            if (Object.prototype.hasOwnProperty.call(cache, key)) {
                return cache[key]
            }
        }
    }
})()

myStorage.set('name', 'Tom')
myStorage.set('age', 20)
console.log(myStorage.get('name')) //   Tom
console.log(myStorage.get('age')) //   20

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/693769.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

六、【源码】SQL执行器的定义和实现

源码地址&#xff1a;https://github.com/mybatis/mybatis-3/ 仓库地址&#xff1a;https://gitcode.net/qq_42665745/mybatis/-/tree/06-sql-executor SQL执行器的定义和实现 之前的Sql执行都是耦合在SqlSession里的&#xff0c;现在要对这部分进行解耦和重构&#xff0c;引…

1奇函数偶函数

文章目录 自变量有理化奇偶性周期性初等函数 自变量 自变量是x&#xff0c;这个还挺奇怪&#xff0c;记住就好 y f ( e x 1 ) yf(e^x1) yf(ex1) 里面 e x e^x ex 只算中间变量&#xff0c;自变量是x 做这些题&#xff0c;想到了以前高中的时候做数学题&#xff0c;不够扎实…

Java 18 的主要新特性和代码演示

默认 UTF-8 从 JDK8 开始&#xff0c;UTF-8 就是 Java SE API 的默认字符集。java.nio.charset.Charset#defaultCharset() 现在默认返回 UTF-8 。现在 Java 的标准 API 都默认使用 UTF-8 编码&#xff0c;目的是让 Java 程序可预测和可移植。在之前&#xff0c; 读取同一个文件…

从《千脑智能》看大模型

千脑智能与大模型 千脑智能介绍 世界模型千脑智能理论——对大脑的全新理解旧大脑&#xff1a;演化的历史烙印新大脑&#xff1a;智慧的创新引擎新旧大脑的互动与争斗启示与借鉴 大脑对信息的处理和建模六根六尘六识 新脑&#xff1a;智能的创新中枢旧脑&#xff1a;生存的本能…

数据结构笔记 4 树和二叉树

二叉树和完全二叉树的区别&#xff1f; 二叉树和完全二叉树的主要区别在于它们的结构特性和节点排列方式&#xff1a; 1. **二叉树**&#xff1a; - 是一种数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;通常称为左子节点和右子节点。 - 节点的子节点数量…

用爬虫实现---模拟填志愿

先来说实现逻辑&#xff0c;首先我要获取到这个网站上所有的信息&#xff0c;那么我们就可以开始对元素进行检查 我们发现他的每一个学校信息都有一个对应的属性&#xff0c;并且是相同的&#xff0c;那么我们就可以遍历这个网页中的所有属性一样的开始爬取 在来分析&#xff0…

探索智慧商场的功能架构与应用

在数字化和智能化的浪潮下&#xff0c;智慧商场已经成为零售业的重要发展方向之一。智慧商场系统的功能架构设计与应用&#xff0c;结合了现代信息技术和零售业的实际需求&#xff0c;为商场的管理和运营提供了全新的解决方案。本文将深入探讨智慧商场的功能架构与应用&#xf…

如何将 Windows图片查看器的背景颜色改成浅色(灰白色)?

现在大家基本都在使用Win10系统&#xff0c;我们在双击查看图片时&#xff0c;系统默认使用系统自带的图片&#xff08;照片&#xff09;查看器去打开图片。图片查看器的背景色默认是黑色的&#xff0c;如下所示&#xff1a;&#xff08;因为大家可能会遇到同样的问题&#xff…

ctfshow-web入门-命令执行(web29)五种解法绕过文件名检测

命令执行&#xff0c;需要严格的过滤 进入 php 代码审计了&#xff1a; 第一题代码很简单&#xff0c;就是对 preg_match 绕过&#xff0c;只要提交的参数值不出现 flag 就行 先看一下当前目录下的文件&#xff0c;构造 payload&#xff1a; ?csystem(ls); 可以看到 flag 就…

MSP432E401Y Launchpad硬件电路

MSP432E401Y是一款32位Arm Cortex-M4F内核的MCU&#xff0c;主频120MHz、256KB SRAM、1MB Flash、6KB EEPROM&#xff0c;具有丰富的通信外设&#xff0c;例如支持以太网、2个CAN、8个UART、4个QSSI(SPI)、10 个I2C; 同时还有2个12 位SAR的ADC模块&#xff0c;每个模块支持高…

【Java】解决Java报错:NullPointerException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 调用 null 对象的实例方法2.2 访问 null 对象的属性2.3 自动拆箱引起的 NullPointerException 3. 解决方案3.1 使用条件判断防止 NullPointerException3.2 优先使用Optional类 4. 预防措施4.1 在方法入口进行校验4.2 使用注解提高…

Elastic 8.14:用于简化分析的 Elasticsearch 查询语言 (ES|QL) 正式发布

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 8.14 正式发布。 什么是新的&#xff1f; 8.14 版本最重要的标题是 ES|QL 的正式发布(GA)&#xff0c;它是从头开始设计和专门构建的&#xff0c;可大大简化数据调查。在新的查询引擎的…

【CTF MISC】XCTF GFSJ0290 reverseMe Writeup(图像处理)

reverseMe 暂无 解法 导入 Photoshop。 水平翻转&#xff0c;得到 flag。 Flag flag{4f7548f93c7bef1dc6a0542cf04e796e}声明 本博客上发布的所有关于网络攻防技术的文章&#xff0c;仅用于教育和研究目的。所有涉及到的实验操作都在虚拟机或者专门设计的靶机上进行&#xf…

实战项目《负载均衡在线OJ系统》

一、项目灵感来源 在日常做题的过程中&#xff0c;我们总会去力扣和牛客网上去做题&#xff0c;但是从来没有想过网站是如何加载给用户的&#xff0c;以及在提交代码时&#xff0c;是如何得知我们的代码是否正确。基于这样的原因&#xff0c;也是学习到一定程度的知识后&#x…

2024真机项目

项目需求&#xff1a; 1. 172.25.250.101 主机上的 Web 服务要求提供 www.exam.com 加密站点&#xff0c;该站点在任何路由可达 的主机上被访问&#xff0c;页面内容显示为 "Hello&#xff0c;Welcome to www.exam.com !"&#xff0c;并提供 content.exam.com/yum/A…

【C语言】文件操作(终卷)

前言 我们在上一卷中了解了顺序读写的函数&#xff0c;现在就让我们从随机读写的函数开始吧。 什么是随机读写&#xff1f; 就是想在哪个位置读或写都行&#xff0c;比较自由。文件打开时光标默认在起始位置。想从后面的某个部分读或写&#xff0c;就得让文件指针来到那个位…

【C语言】宏详解(上卷)

前言 紧接着预处理详解&#xff08;上卷&#xff09;&#xff0c;接下来我们来讲宏&#xff08;隶属于预处理详解系列&#xff09;。 #define定义宏 #define机制包括了一个规定&#xff0c;允许把参数替换到文本中&#xff0c;这种实现通常称为宏&#xff08;macro&#xff…

图解 Python 编程(12) | 文件和编码方式

&#x1f31e;欢迎来到Python 的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年6月9日&am…

使用 Scapy 库编写 TCP 劫持攻击脚本

一、介绍 TCP劫持攻击&#xff08;TCP Hijacking&#xff09;&#xff0c;也称为会话劫持&#xff0c;是一种攻击方式&#xff0c;攻击者在合法用户与服务器之间的通信过程中插入或劫持数据包&#xff0c;从而控制通信会话。通过TCP劫持&#xff0c;攻击者可以获取敏感信息、执…

(2024,扩散,DMP,提示混合,动态门控,阶段特异性,微调)通过混合提示进行扩散模型修补

Diffusion Model Patching via Mixture-of-Prompts 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0 摘要 1 简介 2 相关工作 3 扩散模型修补&#xff08;DMP&#xff09; 3.1 架构…