2020/4/6
HTML:浏览器输入一个地址。到页面展示中间经历了哪些东西?
CSS:前天全国哀悼日,一段css让全站变灰
JavaScript:说下什么是闭包
HTML:浏览器输入一个地址。到页面展示中间经历了哪些东西?
- URL输入
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求
- 服务器响应请求
- 浏览器解析渲染页面
- 连接结束
https://juejin.im/post/5b148a2ce51d4506965908d2
CSS:前天全国哀悼日,一段css让全站变灰
https://juejin.im/post/5e86e221e51d4546ce27b99c
JavaScript:说下什么是闭包
网上对闭包的概念主要分以下两个观点:
- 函数套函数
- 在函数外部获取函数内部变量
但这两个观点都不足以说服什么是闭包
你说函数套函数就是闭包?
const fun = ()=>{
let num = 0;
(function (){
num += 1;
})();
return num;
};
const data = fun();
console.log(data); //1
const data2 = fun();
console.log(data2); //1
const data3 = fun();
console.log(data3); //1
const data4 = fun();
console.log(data4); //1
函数套函数就是用来解释闭包太不严谨,上面的实例代码,每次得到的data都是重新初始化的fun函数,且内部的num每次也都会重新初始化
你说在函数外获取函数内部变量就算是闭包?
function fun() {
var innerVal = '内部变量';
return innerVal;
}
var getInnerVal = fun ();
console.log(getInnerVal);
但是这和闭包没有丝毫关系…
闭包产生的时机
根据《你不知道的JavaScript》中的定义**“当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行**”来查看这段代码:
const fun = ()=>{
let num = 0;
(function (){
num += 1;
})();
return num;
};
fun();
虽然从概念上算是闭包,但似乎没什么作用,因为外部fun函数的执行,也立即执行了内部的匿名函数,则内部匿名函数可以记录num的状态,但由于我们每次都重新初始化fun函数内部的num变量,所以num每次的结果就是1;
简单来说:函数内部保存的变量不随这个函数调用结束而被销毁就是闭包
技术上的闭包:
如何将上面那个没用的闭包变得有用呢?看下面的例子
const fun = ()=>{
let num = 0;
return (v)=>{
return num += v;
};
}
const data5 = fun(); //初始化函数fun并得到函数的匿名函数返回值(这里只初始化了一次)
console.log(data5(1)); //1 给匿名函数传参并得到累加的结果
console.log(data5(1)); //2 由于fun函数未重新初始化,且此时num的值为1,所以累加得2
console.log(data5(1)); //3 与上面雷同
由于主函数的返回值是一个匿名函数,所以我们通过return的方式每次操作那个匿名函数,而这个匿名函数则记录了num的状态,所以就形成了闭包
是不是只有这种return的方式才能形成闭包?
这是一个误解,我们使用其他例子来实现闭包
const obj = new Object();
const fun = ()=>{
let num = 0;
obj.method = (v)=>{
return num += v;
};
};
fun();
console.log(obj.method(1)); // 1
console.log(obj.method(1)); // 2
console.log(obj.method(1)); // 3
console.log(obj.method(1)); // 4
由外部Object对象中的方法来记录函数内部的状态变化
let objFun;
const fun = ()=>{
let num = 0;
objFun = (v)=>{
return num += v;
};
};
fun();
console.log(objFun(1)); // 1
console.log(objFun(1)); // 2
console.log(objFun(1)); // 3
console.log(objFun(1)); // 4
由函数外部的objFun转换为函数记录函数内部变化状态
const arr = [];
const fun = ()=>{
let num = 0;
arr.push((v)=>{
return num += v;
});
};
fun();
const data = arr[0](1);
console.log(data); // 1
const data2 = arr[0](1);
console.log(data2); // 2
由外部数组元素中的函数来保存函数内部的状态变化
所以由此证明了return和闭包没什么关系,只要将内部函数视为可观察可操作的核心,就能够形成闭包。
什么时候需要闭包?
- 读取函数内部的变量
- 保持变量的值始终保持在内存中
参考文章:
https://juejin.im/post/5d61182c51882543e84f41e7
https://juejin.im/post/5b081f8d6fb9a07a9b3664b6
https://juejin.im/post/5d3e55aff265da1bc552ac5d#comment