下面这段 JavaScript 代码,我的参数去哪里呢?

作者站长头像
站长
· 阅读数 19

下面这段 JavaScript 代码,我的参数去哪里呢?

上面这段代码可能变量提升的原因,但是下面我的参数为什么又没被覆盖呢?

下面这段 JavaScript 代码,我的参数去哪里呢?

回复
1个回答
avatar
test
2024-07-12

不要把时间浪费在这种毫无意义的问题上,你应该把时间花在这门语言能干些什么上就以你的这个问题为例用node --print-bytecode --print-bytecode-filter=a a.js生成的字节码是这样的

[generated bytecode for function: a (0x0004e50dbb29 <SharedFunctionInfo a>)]
Bytecode length: 40
Parameter count 2
Register count 2
Frame size 16
OSR nesting level: 0
Bytecode Age: 0
   10 E> 00000004E50DC796 @    0 : 7f 00 00 02       CreateClosure [0], [0], #2 // 创建b函数的一个闭包
         00000004E50DC79A @    4 : 18 03             Star a0  // 将闭包赋值给第一个参数寄存器
   19 S> 00000004E50DC79C @    6 : 21 01 00          LdaGlobal [1], [0]  // 获取全局console
         00000004E50DC79F @    9 : c2                Star1    // 将console存储到r1寄存器中
   27 E> 00000004E50DC7A0 @   10 : 2d f9 02 02       LdaNamedProperty r1, [2], [2]  // 冲常量池中取出字符串'log'
         00000004E50DC7A4 @   14 : c3                Star0 // 将字符串'log'存入寄存器r0中
   27 E> 00000004E50DC7A5 @   15 : 5d fa f9 03 04    CallProperty1 r0, r1, a0, [4] // 调用console他的成员'log' 参数为a0(先前被赋值为b的一个闭包)
   46 S> 00000004E50DC7AA @   20 : 0d 0a             LdaSmi [10] // 将10载入acc寄存器
         00000004E50DC7AC @   22 : 18 03             Star a0  // 从acc寄存器去除10到a0寄存器
   72 S> 00000004E50DC7AE @   24 : 21 01 00          LdaGlobal [1], [0] // 又是加载console的逻辑同上
         00000004E50DC7B1 @   27 : c2                Star1
   80 E> 00000004E50DC7B2 @   28 : 2d f9 02 02       LdaNamedProperty r1, [2], [2]
         00000004E50DC7B6 @   32 : c3                Star0
   80 E> 00000004E50DC7B7 @   33 : 5d fa f9 03 06    CallProperty1 r0, r1, a0, [6] // 再次调用注意这里a0的值已经存储了小整数10
         00000004E50DC7BC @   38 : 0e                LdaUndefined // 加载undefined到acc寄存器上
   89 S> 00000004E50DC7BD @   39 : a8                Return  // 函数返回
Constant pool (size = 3)
00000004E50DC739: [FixedArray] in OldSpace
 - map: 0x03c05fd812c1 <Map>
 - length: 3
           0: 0x0004e50dc6e9 <SharedFunctionInfo b>
           1: 0x00f3dff21bb1 <String[7]: #console>
           2: 0x0146912a9f31 <String[3]: #log>
Handler Table (size = 0)
Source Position Table (size = 20)
0x0004e50dc7c1 <ByteArray[20]>

可以看到不管是函数b,还是重新的变量声明b都被当作了对a0寄存器的重新赋值(a0在这里表示为第一个参数寄存器),所以他的等价代码应该为

function a(b) {
  b = function b(){}; 
  console.log(b);
  b = 10;
  console.log(b);
}

a(1);

没人会写这种代码,相比这种毫无价值的问题,你更应该去了解,字节码是什么,什么是栈式虚拟机,什么是寄存器虚拟机,编译器是什么,闭包是怎么实现的v8字节码解释还有什么不懂可以问chatgpt

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容