当前位置: 首页 > news >正文

【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() // 2console.log("---------- 用完就删 --------")
function hd2() {let n = 1;function sum() {console.log(++n)}sum()
}
hd2()   // 2
hd2()   // 2
hd2()   // 2console.log("-------------------------------")
const hd3 = () => {let n = 1;return () => {const m = () => console.log(++n)m()}
}
hd3()() // 2
hd3()() // 2console.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}`) // 4for (let j = 1; j <= 3; j++) {console.log(`for里面: ${j}`)
}
// console.log(`for外面: ${j}`) // ReferenceError: j is not definedconsole.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]()); // 3console.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]()) // 4console.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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 计网总结☞网络层
  • 吊车报警的工作原理和使用场景_鼎跃安全
  • SecureCRT[po破] for Mac SSH终端操作工具[解] 安装教程
  • Docker快速部署springboot项目
  • 冯喜运:6.10周一黄金还会再次拉升吗?日内黄金原油操作策略
  • 简单介绍一下vim
  • Uniapp与第三方应用数据通讯
  • 【数据结构】详解堆排序当中的topk问题(leetcode例题)
  • HTML 中使用 JavaScript 的具体方式
  • PHP实现一个简单的接口签名方法以及思路分析
  • 单片机(STM32)与上位机传输浮点数
  • 20240606更新Toybrick的TB-RK3588开发板在Android12下的内核
  • kafka-生产者事务-数据传递语义事务介绍事务消息发送(SpringBoot整合Kafka)
  • 个人博客搭建
  • Android 蓝牙profile的配置
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【node学习】协程
  • 07.Android之多媒体问题
  • Android Volley源码解析
  • Fabric架构演变之路
  • Linux gpio口使用方法
  • Swift 中的尾递归和蹦床
  • unity如何实现一个固定宽度的orthagraphic相机
  • 使用 QuickBI 搭建酷炫可视化分析
  • 算法-插入排序
  • 译自由幺半群
  • python最赚钱的4个方向,你最心动的是哪个?
  • 大数据全解:定义、价值及挑战
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​补​充​经​纬​恒​润​一​面​
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (回溯) LeetCode 78. 子集
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (转)socket Aio demo
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .net知识和学习方法系列(二十一)CLR-枚举
  • @Bean有哪些属性
  • @font-face 用字体画图标
  • @RequestMapping用法详解
  • @staticmethod和@classmethod的作用与区别
  • [ C++ ] STL_vector -- 迭代器失效问题
  • []我的函数库
  • [04]Web前端进阶—JS伪数组
  • [2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [8-23]知识梳理:文件系统、Bash基础特性、目录管理、文件管理、文本查看编辑处理...
  • [android] 切换界面的通用处理