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