一个故事讲闭包

昨天给一位朋友讲解闭包,讲解过程中想到一种故事型的讲解方式,朋友听了直呼内行。

你说的这个朋友到底是不是...

首先看一段简单到哭的代码;

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 变量封闭保护起来。
  • 函数作为值传递。由于函数作为一等公民,可以像变量一样被赋值,可以作为值传递,也可以作为返回值返回,所以才能让函数这个「闭包」顺利逃离灾难现场,逃离被摧毁的命运。

你可能感兴趣的:(一个故事讲闭包)