每日3题(31)

2020/4/6

HTML:浏览器输入一个地址。到页面展示中间经历了哪些东西?

CSS:前天全国哀悼日,一段css让全站变灰

JavaScript:说下什么是闭包

HTML:浏览器输入一个地址。到页面展示中间经历了哪些东西?

  1. URL输入
  2. DNS解析
  3. TCP连接
  4. 发送HTTP请求
  5. 服务器处理请求
  6. 服务器响应请求
  7. 浏览器解析渲染页面
  8. 连接结束

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


闭包原文链接

发布了49 篇原创文章 · 获赞 1 · 访问量 1080

猜你喜欢

转载自blog.csdn.net/weixin_44194732/article/details/105341411