历史小剧场
明朝灭亡,并非是简单的政治问题,事实上,这是世界经济史上的一个重要案例。
所谓没钱,就是没有白银。----《明朝那些事儿》
什么是闭包?
闭包就是指有权访问另一个函数作用域中变量的函数
闭包变量存储位置?
- 堆内存
假如闭包中的变量存储在栈内存中,那么栈的回收,会把处于栈顶的变量自动回收。所以闭包中的变量如果处于栈中那么变量被销毁后,闭包中的变量就没有了。所以闭包中的变量是处于堆内存中的。
闭包的作用?
- 创造私有变量,且延长私有变量的生命周期
应用
- 延伸函数生命周期
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
- 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)
}
- 多层作用域嵌套
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
- 获取商品区间以及商品排序
商品区间
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>
- 实现缓存模拟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