1、题目一

  1. let x = 5;
  2. function fn(x) {
  3. return function (y) {
  4. console.log(y + (++x));
  5. }
  6. }
  7. let f = fn(6);
  8. f(7); // 7+(6+1)= 14
  9. fn(8)(9); //9+(8+1)= 18
  10. f(10); //10+(7+1) = 18 注意此时这里的x已经是7,经过fn(6)后做了一次++x处理变成7保留着。
  11. console.log(x); // 5

image.png
函数执行前需要做如下几个事情:

  • 初始化作用域链[[scope]]: <当前上下文,函数的作用域(函数fn创建时候所处的上下文)>
  • 初始化this指向
  • 初始化arguments
  • 形参赋值
  • 变量提升

[一般情况下]
函数执行完成后,所形成的私有上下文,都会出栈”释放”。

  • 私有上下文中的一切内容都会被销毁
  • 优化栈内存空间

[特殊情况]
如果函数执行所形成的上下文中,如果出现引用类型的空间地址被当前上下文以外的事物所占用,那么当前上下文是不能够出栈释放的。

  • 上下文中的信息保留下来(包含私有变量和值)
  • 导致栈内存空间变大

下图中,0x000001被小f占用,堆内存不能够被释放。
image.png
EC(FN1) 代表fn(6)第一次执行。
f(7) -> 0x000001(7) 执行完后释放
EC(FN2)代表fn(8)第二次执行。 EC(FN2)是全新的,和EC(FN1) 没关系,fn(6)没有被释放。
f(8)(9) -> 0x000000(8) 先执行fn(8),返回结果 紧接着执行传递实参9, 0x000002(9) 。

堆0x000000 临时不会被出栈释放,因为返回的结果需要在外部用一次,等到0x000002(9) 执行完,再出栈释放。

f(10)->0x000001(10)

1.png

++i 和 i++

  • 都是自身基础上累加1,累加和运算的顺序不一样
  • i=1 5+(i++) 运算结果:6 i:2 “先运算在累加”
  • i=1 5+(++i) i:2 运算结果:7 “先累加在运算”