一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

    image.png
    image.png

    1. function books(){
    2. var book = '书包里的书本';
    3. return function(){
    4. console.log(book);
    5. }
    6. }
    7. var bag = books();
    8. bag();
    9. // 匿名函数执行上下文 = {作用域链: {匿名函数变量对象 + books变量对象 + 全局变量对象}, {变量对象: }}
    10. // books执行上下文 = {作用域链: {books变量对象 + 全局变量对象}, {变量对象: book}}
    11. // 全局执行上下文 = {作用域链: {全局变量对象}, {变量对象: books, bag}}
    1. for(var i = 0; i < 5; i++){
    2. (function(x){
    3. console.log(x++);
    4. })(i);
    5. }
    6. console.log(i);
    7. // 立即执行函数执行上下文 = {作用域链: {立即执行函数变量对象 + 全局变量对象}, {变量对象: x}}
    8. // 全局执行上下文 = {作用域链: {全局变量对象}, {变量对象: i}}
    1. for(var i = 0; i < 5; i++){
    2. setTimeout(function(){
    3. console.log(i++);
    4. });
    5. }
    6. console.log(i);
    7. // 输出为 5 5 6 7 8 9
    1. for(var i = 0; i < 5; i++){
    2. (function(x){
    3. setTimeout(function(){
    4. console.log(x);
    5. },4000)
    6. })(i)
    7. }
    8. console.log(i);
    9. // 输出为 5 0 1 2 3 4
    1. <!DOCTYPE html>
    2. <html>
    3. <script>
    4. var b = 'boy';
    5. console.log(b);
    6. function fighting(){
    7. console.log(a);
    8. console.log(b);
    9. if(a === 'apple'){
    10. a = 'Alice';
    11. }else{
    12. a = 'Ada';
    13. }
    14. console.log(a);
    15. var a = 'Andy';
    16. middle();
    17. function middle(){
    18. console.log(c++);
    19. var c = 100;
    20. console.log(++c);
    21. samall();
    22. function samall(){
    23. console.log(a);
    24. }
    25. }
    26. var c = a = 88;
    27. function bottom(){
    28. console.log(this.b);
    29. b = 'baby';
    30. console.log(b);
    31. }
    32. bottom();
    33. }
    34. fighting();
    35. console.log(b);
    36. </script>
    37. </html>