+
+在上面的代码中,我们在函数 *a* 中定义了一个变量 *i*,然后打印这个 *i* 变量。对于 *a* 这个函数来讲,自己的函数作用域中存在 *i* 这个变量,所以我们在调试时可以看到 *Local* 中存在变量 *i*。
+
+
+
+下面我们将上面的代码稍作修改,如下图:
+
+
+
+在上面的代码中,我们将声明 *i* 这个变量的动作放到了 *a* 函数外面,也就是说 *a* 函数在自己的作用域已经找不到这个 *i* 变量了,它会怎么办?
+
+学习了作用域链的你肯定知道,它会顺着作用域链一层一层往外找。然而上面在介绍闭包时说过,如果出现了这种情况,也就是函数使用了外部的数据的情况,就会创建闭包。
+
+仔细观察调试区域,我们会发现此时的 *i* 就放在 *Closure* 里面的,从而证实了我们前面的说法。
+
+
+
+所以你看,闭包其实也没有那么难理解,当你觉得一个词对你来说特别难的时候,你还可以使用拆词法,这也是我比较推荐的屡试不爽的一种方法。
+
+
+
+“闭”可以理解为“封闭,闭环”,“包”可以理解为“一个类似于包裹的空间”,因此闭包实际上可以看作是一个封闭的空间,那么这个空间用来干啥呢?实际上就是用来存储变量的。
+
+
+
+那么是一个函数下所有的变量声明都会被放入到闭包这个封闭的空间里面么?
+
+倒也不是,放不放入到闭包中,要看其他地方有没有对这个变量进行引用,例如:
+
+
+
+在上面的代码中,函数 c 中一个变量都没有创建,却要打印 *i、j、k* 和 *x*,这些变量分别存在于 *a、b* 函数以及全局作用域中,因此创建了 *3* 个闭包,全局闭包里面存储了 *i* 的值,闭包 *a* 中存储了变量 *j* 和 *k* 的值,闭包 *b* 中存储了变量 *x* 的值。
+
+但是你仔细观察,你就会发现函数 *b* 中的 *y* 变量并没有被放在闭包中,所以要不要放入闭包取决于该变量有没有被引用。
+
+
+
+当然,此时的你可能会有这样的一个新问题,那么多闭包,那岂不是占用内存空间么?
+
+实际上,如果是自动形成的闭包,是会被销毁掉的。例如:
+
+
+
+在上面的代码中,我们在第 *16* 行尝试打印输出变量 *k*,显然这个时候是会报错的,在第 *16* 行打一个断点调试就可以清楚的看到,此时已经没有任何闭包存在,垃圾回收器会自动回收没有引用的变量,不会有任何内存占用的情况。
+
+
+
+当然,这里我指的是自动产生闭包的情况,关于闭包,有时我们需要根据需求手动的来制造一个闭包。
+
+来看下面的例子:
+
+```js
+function eat(){
+ var food = "鸡翅";
+ console.log(food);
+}
+eat(); // 鸡翅
+console.log(food); // 报错
+```
+
+在上面的例子中,我们声明了一个名为 *eat* 的函数,并对它进行调用。
+
+*JavaScript* 引擎会创建一个 *eat* 函数的执行上下文,其中声明 *food* 变量并赋值。
+
+当该方法执行完后,上下文被销毁,*food* 变量也会跟着消失。这是因为 *food* 变量属于 *eat* 函数的局部变量,它作用于 *eat* 函数中,会随着 *eat* 的执行上下文创建而创建,销毁而销毁。所以当我们再次打印 *food* 变量时,就会报错,告诉我们该变量不存在。
+
+
+
+但是我们将此代码稍作修改:
+
+```js
+function eat(){
+ var food = '鸡翅';
+ return function(){
+ console.log(food);
+ }
+}
+var look = eat();
+look(); // 鸡翅
+look(); // 鸡翅
+```
+
+在这个例子中,*eat* 函数返回一个函数,并在这个内部函数中访问 *food* 这个局部变量。调用 *eat* 函数并将结果赋给 *look* 变量,这个 *look* 指向了 *eat* 函数中的内部函数,然后调用它,最终输出 *food* 的值。
+
+为什么能访问到 *food*,原因很简单,上面我们说过,垃圾回收器只会回收没有被引用到的变量,但是一旦一个变量还被引用着的,垃圾回收器就不会回收此变量。在上面的示例中,照理说 *eat* 调用完毕 *food* 就应该被销毁掉,但是我们向外部返回了 *eat* 内部的匿名函数,而这个匿名函数有引用了 *food*,所以垃圾回收器是不会对其进行回收的,这也是为什么在外面调用这个匿名函数时,仍然能够打印出 *food* 变量的值。
+
+
+
+至此,闭包的一个优点或者特点也就体现出来了,那就是:
+
+- 通过闭包可以让外部环境访问到函数内部的局部变量。
+- 通过闭包可以让局部变量持续保存下来,不随着它的上下文环境一起销毁。
+
+
+
+通过此特性,我们可以解决一个全局变量污染的问题。早期在 *JavaScript* 还无法进行模块化的时候,在多人协作时,如果定义过多的全局变量 有可能造成全局变量命名冲突,使用闭包来解决功能对变量的调用将变量写到一个独立的空间里面,从而能够一定程度上解决全局变量污染的问题。
+
+例如:
+
+```js
+var name = "GlobalName";
+// 全局变量
+var init = (function () {
+ var name = "initName";
+ function callName() {
+ console.log(name);
+ // 打印 name
+ }
+ return function () {
+ callName();
+ // 形成接口
+ }
+}());
+init(); // initName
+var initSuper = (function () {
+ var name = "initSuperName";
+ function callName() {
+ console.log(name);
+ // 打印 name
+ }
+ return function () {
+ callName();
+ // 形成接口
+ }
+}());
+initSuper(); // initSuperName
+```
+
+
+
+好了,在此小节的最后,我们来对闭包做一个小小的总结:
+
+
+
+- 闭包是一个封闭的空间,里面存储了在其他地方会引用到的该作用域的值,在 *JavaScript* 中是通过作用域链来实现的闭包。
+
+
+
+- 只要在函数中使用了外部的数据,就创建了闭包,这种情况下所创建的闭包,我们在编码时是不需要去关心的。
+
+
+
+- 我们还可以通过一些手段手动创建闭包,从而让外部环境访问到函数内部的局部变量,让局部变量持续保存下来,不随着它的上下文环境一起销毁。
+
+
+
+## 闭包经典问题
+
+聊完了闭包,接下来我们来看一个闭包的经典问题。
+
+```js
+for (var i = 1; i <= 3; i++) {
+ setTimeout(function () {
+ console.log(i);
+ }, 1000);
+}
+```
+
+在上面的代码中,我们预期的结果是过 *1* 秒后分别输出 *i* 变量的值为 *1,2,3*。但是,执行的结果是:*4,4,4*。
+
+实际上,问题就出在闭包身上。你看,循环中的 *setTimeout* 访问了它的外部变量 *i*,形成闭包。
+
+而 *i* 变量只有 *1* 个,所以循环 *3* 次的 *setTimeout* 中都访问的是同一个变量。循环到第 *4* 次,*i* 变量增加到 *4*,不满足循环条件,循环结束,代码执行完后上下文结束。但是,那 *3* 个 *setTimeout* 等 *1* 秒钟后才执行,由于闭包的原因,所以它们仍然能访问到变量 *i*,不过此时 *i* 变量值已经是 *4* 了。
+
+要解决这个问题,我们可以让 *setTimeout* 中的匿名函数不再访问外部变量,而是访问自己内部的变量,如下:
+
+```js
+for (var i = 1; i <= 3; i++) {
+ (function (index) {
+ setTimeout(function () {
+ console.log(index);
+ }, 1000);
+ })(i)
+}
+```
+
+这样 *setTimeout* 中就可以不用访问 *for* 循环声明的变量 *i* 了。而是采用调用函数传参的方式把变量 *i* 的值传给了 *setTimeout*,这样它们就不再创建闭包,因为在我自己的作用域里面能够找到 *i* 这个变量。
+
+当然,解决这个问题还有个更简单的方法,就是使用 *ES6* 中的 *let* 关键字。
+
+它声明的变量有块作用域,如果将它放在循环中,那么每次循环都会有一个新的变量 *i*,这样即使有闭包也没问题,因为每个闭包保存的都是不同的 *i* 变量,那么刚才的问题也就迎刃而解。
+
+```js
+for (let i = 1; i <= 3; i++) {
+ setTimeout(function () {
+ console.log(i);
+ }, 1000);
+}
+```
+
+
+
+## 真题解答
+
+
+
+- 闭包是什么?闭包的应用场景有哪些?怎么销毁闭包?
+
+>闭包是一个封闭的空间,里面存储了在其他地方会引用到的该作用域的值,在 *JavaScript* 中是通过作用域链来实现的闭包。
+>
+>只要在函数中使用了外部的数据,就创建了闭包,这种情况下所创建的闭包,我们在编码时是不需要去关心的。
+>
+>我们还可以通过一些手段手动创建闭包,从而让外部环境访问到函数内部的局部变量,让局部变量持续保存下来,不随着它的上下文环境一起销毁。
+>
+>使用闭包可以解决一个全局变量污染的问题。
+>
+>如果是自动产生的闭包,我们无需操心闭包的销毁,而如果是手动创建的闭包,可以把被引用的变量设置为 *null*,即手动清除变量,这样下次 *JavaScript* 垃圾回收器在进行垃圾回收时,发现此变量已经没有任何引用了,就会把设为 *null* 的量给回收了。
+
+
+
+------
+
+
+
+-*EOF*-
\ No newline at end of file
diff --git a/11. DOM事件的注册和移除/DOM 事件的注册和移除.html b/12. DOM事件的注册和移除/DOM 事件的注册和移除.html
similarity index 100%
rename from 11. DOM事件的注册和移除/DOM 事件的注册和移除.html
rename to 12. DOM事件的注册和移除/DOM 事件的注册和移除.html
diff --git a/11. DOM事件的注册和移除/DOM 事件的注册和移除.md b/12. DOM事件的注册和移除/DOM 事件的注册和移除.md
similarity index 100%
rename from 11. DOM事件的注册和移除/DOM 事件的注册和移除.md
rename to 12. DOM事件的注册和移除/DOM 事件的注册和移除.md
diff --git a/12. DOM事件的传播机制/DOM 事件的传播机制.html b/13. DOM事件的传播机制/DOM 事件的传播机制.html
similarity index 100%
rename from 12. DOM事件的传播机制/DOM 事件的传播机制.html
rename to 13. DOM事件的传播机制/DOM 事件的传播机制.html
diff --git a/12. DOM事件的传播机制/DOM 事件的传播机制.md b/13. DOM事件的传播机制/DOM 事件的传播机制.md
similarity index 100%
rename from 12. DOM事件的传播机制/DOM 事件的传播机制.md
rename to 13. DOM事件的传播机制/DOM 事件的传播机制.md
diff --git a/13. 阻止事件的默认行为/阻止事件默认行为.html b/14. 阻止事件的默认行为/阻止事件默认行为.html
similarity index 100%
rename from 13. 阻止事件的默认行为/阻止事件默认行为.html
rename to 14. 阻止事件的默认行为/阻止事件默认行为.html
diff --git a/13. 阻止事件的默认行为/阻止事件默认行为.md b/14. 阻止事件的默认行为/阻止事件默认行为.md
similarity index 100%
rename from 13. 阻止事件的默认行为/阻止事件默认行为.md
rename to 14. 阻止事件的默认行为/阻止事件默认行为.md
diff --git a/14. 递归/递归.js b/15. 递归/递归.js
similarity index 100%
rename from 14. 递归/递归.js
rename to 15. 递归/递归.js
diff --git a/14. 递归/递归.md b/15. 递归/递归.md
similarity index 100%
rename from 14. 递归/递归.md
rename to 15. 递归/递归.md
diff --git a/15. 属性描述符/属性描述符.js b/16. 属性描述符/属性描述符.js
similarity index 100%
rename from 15. 属性描述符/属性描述符.js
rename to 16. 属性描述符/属性描述符.js
diff --git a/15. 属性描述符/属性描述符.md b/16. 属性描述符/属性描述符.md
similarity index 100%
rename from 15. 属性描述符/属性描述符.md
rename to 16. 属性描述符/属性描述符.md
diff --git a/16. Class和普通构造器的区别/class 和构造函数区别.js b/17. Class和普通构造器的区别/class 和构造函数区别.js
similarity index 100%
rename from 16. Class和普通构造器的区别/class 和构造函数区别.js
rename to 17. Class和普通构造器的区别/class 和构造函数区别.js
diff --git a/16. Class和普通构造器的区别/class 和构造函数区别.md b/17. Class和普通构造器的区别/class 和构造函数区别.md
similarity index 100%
rename from 16. Class和普通构造器的区别/class 和构造函数区别.md
rename to 17. Class和普通构造器的区别/class 和构造函数区别.md
diff --git a/17. 浮点数精度问题/浮点数精度问题.js b/18. 浮点数精度问题/浮点数精度问题.js
similarity index 100%
rename from 17. 浮点数精度问题/浮点数精度问题.js
rename to 18. 浮点数精度问题/浮点数精度问题.js
diff --git a/17. 浮点数精度问题/浮点数精度问题.md b/18. 浮点数精度问题/浮点数精度问题.md
similarity index 100%
rename from 17. 浮点数精度问题/浮点数精度问题.md
rename to 18. 浮点数精度问题/浮点数精度问题.md
diff --git a/18. 严格模式/严格模式.js b/19. 严格模式/严格模式.js
similarity index 100%
rename from 18. 严格模式/严格模式.js
rename to 19. 严格模式/严格模式.js
diff --git a/18. 严格模式/严格模式.md b/19. 严格模式/严格模式.md
similarity index 100%
rename from 18. 严格模式/严格模式.md
rename to 19. 严格模式/严格模式.md
diff --git a/19. 函数防抖和节流/函数防抖和节流.html b/20. 函数防抖和节流/函数防抖和节流.html
similarity index 100%
rename from 19. 函数防抖和节流/函数防抖和节流.html
rename to 20. 函数防抖和节流/函数防抖和节流.html
diff --git a/19. 函数防抖和节流/函数防抖和节流.md b/20. 函数防抖和节流/函数防抖和节流.md
similarity index 100%
rename from 19. 函数防抖和节流/函数防抖和节流.md
rename to 20. 函数防抖和节流/函数防抖和节流.md
diff --git a/25. eval/eval.js b/25. eval/eval.js
new file mode 100644
index 0000000..e76e3e6
--- /dev/null
+++ b/25. eval/eval.js
@@ -0,0 +1,40 @@
+"use strict"
+// eval('console.log("Hello World")')
+
+var str = `
+ var a = 1;
+ var b = 2;
+ if(a > b) {
+ console.log('a > b');
+ } else {
+ console.log('a
+
+
+
+
+
+
+
+
+
+------
+
+
+
+-*EOF*-
+
diff --git a/知识图谱.dio b/知识图谱.dio
index 063852c..49c6607 100644
--- a/知识图谱.dio
+++ b/知识图谱.dio
@@ -1,125 +1,125 @@