1. let x = 5;
  2. function fn() {
  3. return function (y) {
  4. console.log(y+ (++x));
  5. }
  6. }
  7. let f = fn(6);
  8. f(7);
  9. fn(8)(9);
  10. f(10);
  11. console.log(x);
  1. /**
  2. * EC(G)
  3. * x = 5; //6 7 8
  4. * fn = 0x000000; [[scope]]:EC(G)
  5. * f = 0x000001;
  6. **/
  7. let x = 5;
  8. function fn() {
  9. /*
  10. * fn第一次执行 0x000000(6)
  11. * EC(fn1)
  12. * 作用域链:<EC(fn1),EC(G)>
  13. * 形参赋值:--
  14. * 代码执行:
  15. * 创建一个函数 0x000001; [[scope]]:EC(fn1) 形参:y
  16. * return 0x000001;
  17. * “不被释放”
  18. */
  19. /*
  20. * fn(8) 第二次执行fn 0x000000(8)
  21. * EC(fn2)
  22. * 作用域链:<EC(fn2),EC(G)>
  23. * 形参赋值:--
  24. * 代码执行:
  25. * 创建一个函数 0x000002; [[scope]]:EC(fn2) 形参:y
  26. * return 0x000002;
  27. * “临时不被释放”
  28. */
  29. return function (y) {
  30. /*
  31. * f(7) EC(f1)
  32. * 作用域链:<EC(f1),EC(fn1)>
  33. * 形参赋值:y=7
  34. * 代码执行:
  35. * y+(++x) =>13
  36. */
  37. /*
  38. * 0x000002(9) EC(any) any代表倪明函数
  39. * 作用域链:<EC(any),EC(fn2)>
  40. * 形参赋值:y=9
  41. * 代码执行:
  42. * y+(++x) =>16
  43. */
  44. /*
  45. * f(10) 0x000001(10) EC(f2)
  46. * 作用域链:<EC(f2),EC(fn1)>
  47. * 形参赋值:y=10
  48. * 代码执行:
  49. * y+(++x) => 18
  50. */
  51. console.log(y + (++x));
  52. }
  53. }
  54. let f = fn(6);
  55. f(7); // 7+(++5) = 13
  56. fn(8)(9); // 9+ (++6) = 16
  57. f(10); // 10 + (++7) = 18
  58. console.log(x); //=> 8

GC:浏览器垃圾回收机制(内存释放机制)

【栈内存:EC】

全局执行上下文:在浏览器加载页面的时候形成,然后会在页面关闭的时候释放(页面刷新:先释放,重新加载后再形成)
私有上下文:函数执行会形成一个私有的上下文(let/const也会产生私有的上下文)

  • 一般情况下代码执行完就会被出栈释放
  • 如果当前上下文中的某个内容(一般是一个堆[对象/函数])被上下文以外的事物占用了,则当前上下文不能被释放

    【堆内存:HEAP】

    谷歌浏览器按照“是否被引用”来决定堆内存的释放还是不释放的:浏览器会定期间隔一段时间,查找所有堆内存是否被占用,被占用的不处理,但是如果没有被占用,则直接把它释放掉

  • 我们可以基于手动赋值为null的方式结束堆内存的占用,来达到释放内存的目的


    IE浏览器是根据“引用计数”方式实现垃圾回收的:每次被占用都会计数累加,相反取消引用,则计数累减,直到计数为零,则释放内存

  • 这种方式经常会出现记着记着就乱了 “内存泄漏”

  • 扩展任务:javascript高级程序设计第三版,最后章节中有内存泄漏的问题,自己回去看看 ```javascript // 堆内存name: ‘erina’}不会被释放,因为被obj占用了 let obj = { name: ‘erina’ }

obj = null ; // 可以释放堆内存

  1. <br />** 函数执行,会形成一个私有的上下文,这个私有上下文会保护里面的私有变量不受外界的干扰,我们把函数的这种“保护机制”称之为“闭包”;**但是一般情况下,执行完上下文就被释放了,所以闭包作用时间太短了,所以市面上一般都认为:“**函数执行,形成一个不被释放的上下文,一方面可以保护里面的私有变量不受外界干扰【保护】,另一方面也可以把这些私有变量值存储下来【保存】,这种方式才是闭包!**”
  2. - 闭包机制会消耗计算机的内存(合理使用)
  3. - 闭包的作用:保存/保护
  4. 闭包的表现形式:
  5. - 大函数嵌套小函数,小函数中用到大函数的内容
  6. - <br />
  7. ```javascript
  8. function fn() {
  9. let x = 10;
  10. //fn执行,在私有上下文中创建了一个子函数(堆内存的地址),函数的地址返回给fn以外的f,f就占用了这个函数
  11. // 当前形成的上下文不会被释放,形成闭包
  12. return function () {
  13. console.log(++x)
  14. }
  15. }
  16. let f = fn();
  17. f(); // 11
  18. f(); // 12
  19. f(); // 13

    1. function fn() {
    2. let obj = {
    3. name: 'xxx'
    4. };
    5. // 在函数里面创建对象,被外面全局的obj占用,形成闭包
    6. return obj;
    7. }
    8. let obj = fn();

    1. function fn() {
    2. let x = 0;
    3. // window.xxx = function(){};
    4. document.body.onclick = function () {
    5. console.log(++x);
    6. }
    7. }
    8. fn();