一个故事讲闭包
2020-05-31 本文已影响0人
401
昨天给一位朋友讲解闭包,讲解过程中想到一种故事型的讲解方式,朋友听了直呼内行。
你说的这个朋友到底是不是...
首先看一段简单到哭的代码;
const funcA = function () {
const x = 1;
}
funcA();
console.log('x 是我得不到的人:', x);
由于 x 是 funcA 的局部变量,作用域范围在 funcA 函数内部,外部的 console 无法访问 x。
假如我一定要获得局部变量 x 呢?那么可以通过:
const funcA = function () {
const x = 1;
return x; // 通过 return 让 x 躲过被摧毁的命运
}
const x = funcA();
console.log('得到 x 了:', x);
但是上述实现没有什么私密性可言,这样方式岂不是让所有人都可以随意得到 x 了吗?如何能够更加私密的得到 x ?答案就是「闭包」。
一个故事
看一段悲伤到哭的故事:
// 一个温馨的家
const home = function () {
const child = 'L'; // 有一个名为 L 的孩子
const child_home = 'None'; // 孩子还没有自己的家,没有自己的保护壳
return child_home;
};
// child 随着 home 的结束而被无情的摧毁
// 但还有一点希望:child_home 通过返回值「活下来」了
const alive = home();
// 但结局最终是悲伤的:child_home 里空空如也,只有一个冷冰冰的 None.
// child 没能幸还
console.log('alive: ', alive);
一个温馨的家保护着温室里的花朵:一个正在成长中的孩子。但由于种种原因,这个温馨的家不再温馨,「家」已经结束了,那个孩子也被彻底摧毁了。
男泪女泪!救救孩子吧!
// 一个温馨的家
const home = function () {
const child = 'L'; // 有一个名为 L 的孩子
// 内心强大的孩子构建了自己的家!
// child_home 将 child 拥抱入怀中,
// 将它「封闭」在了自己的「包」中
// child_home 是 child 以及其他孩子们的新家
// 孩子给这个新家起名为「闭包」!
const child_home = function (check) {
const child_inner = child;
if (check == 'child, it\'s me!') return child_inner;
}
// return 将为这个新家 child_home 开启一个避难通道!
// 在 home 摧毁时
// child_home 这个「闭包」完整的保护着新家的环境(函数上下文)
// child_home 带着孩子们(局部变量)逃离了灾难现场!
return child_home;
};
// home 结束
// 但 child_home 通过返回值「活下来」了
const alive = home();
// child 也活下来了!
// 而且把自己保护的很好,需要人脸识别,才能家访!
console.log('alive: ', alive('child, it\'s me!'));
孩子最终成长到内心足够强大,构建了自己的新家,新家把自己保护起来,形成一个「闭包」,在原始家庭结束的时候逃离了灾难现场。同时如果有需要,还能把自己保护的很好,即使逃离后也不是任何人都能访问。
救出孩子了!男笑女笑!
总结
从上面可以知道「闭包」能够实现的两个核心点:
- 词法作用域。即 home 函数内定义的 child_home 函数,能够按照代码书写的顺序,访问到 home 函数内部且在 child_home 之前定义的变量。因为词法作用域的存在,child_home 才能把 child 变量封闭保护起来。
- 函数作为值传递。由于函数作为一等公民,可以像变量一样被赋值,可以作为值传递,也可以作为返回值返回,所以才能让函数这个「闭包」顺利逃离灾难现场,逃离被摧毁的命运。
汪
汪