在javascript中,为什么默认参数在函数内部是不可变的?

在javascript中,为什么默认参数在函数内部是不可变的?,javascript,arguments,immutability,default-arguments,Javascript,Arguments,Immutability,Default Arguments,为什么在javascript中,默认参数不能在函数内部更改,而非默认参数可以更改 function func(a) { a = 99; // updating a also updates arguments[0] console.log(arguments[0]); } func(10); // prints 99 vs 看看: 仅传递简单参数(即,不是rest、默认或重构参数)的非严格函数将使函数体中的变量值和新值与arguments对象同步,反之亦然: 而且 function f

为什么在javascript中,默认参数不能在函数内部更改,而非默认参数可以更改

function func(a) {
  a = 99; // updating a also updates arguments[0]
  console.log(arguments[0]);
}
func(10); // prints 99
vs

看看:

仅传递简单参数(即,不是rest、默认或重构参数)的非严格函数将使函数体中的变量值和新值与arguments对象同步,反之亦然:

而且

function func(a) {
  a = 99; // updating a also updates arguments[0]
  console.log(arguments[0]);
}
func(10); // 99
// An untracked default parameter
function func(a = 55) {
  console.log(arguments[0]);
}
func(); // undefined
相反,传递rest、default或destructured参数的非严格函数不会将函数体中分配给参数变量的新值与arguments对象同步。相反,具有复杂参数的非严格函数中的arguments对象将始终反映调用函数时传递给函数的值(这与所有严格模式函数所表现的行为相同,无论传递的变量类型如何):

而且

function func(a) {
  a = 99; // updating a also updates arguments[0]
  console.log(arguments[0]);
}
func(10); // 99
// An untracked default parameter
function func(a = 55) {
  console.log(arguments[0]);
}
func(); // undefined
这可能是由于javascript编译器中的同步进程语法糖出现了一些问题

更新:

原来
deno
在引擎盖下做了一些不同的事情,在这两种情况下打印
10
,这有点奇怪,所以我查看了这里生成的程序集:

deno eval 'function f(a) { a = 99; console.log(arguments[0]); } f(10);' --v8-flags='--print-bytecode,--print-bytecode-filter=f'
deno eval 'function f(a = 55) { arguments[0] = 99; console.log(a); } f(10);' --v8-flags='--print-bytecode,--print-bytecode-filter=f'
第一个命令打印我试图理解的代码,将注释放在我认为它在做相关的事情的地方

[generated bytecode for function: f (0x38db0826b679 <SharedFunctionInfo f>)]
Parameter count 2
Register count 4
Frame size 32
    0x38db0826b846 @    0 : 88                CreateUnmappedArguments
    0x38db0826b847 @    1 : 26 fb             Star r0: Store accumulator in register 0 (presumibly function frame pointer)
    0x38db0826b849 @    3 : 0c 63             LdaSmi [99]: Load (SMallInteger) 99 in accumulator
    0x38db0826b84b @    5 : 26 02             Star a0: Store accumulator in function argument 0
    0x38db0826b84d @    7 : 13 00 00          LdaGlobal [0], [0]: I don't know
    0x38db0826b850 @   10 : 26 f9             Star r2: Store accumulator in register 2
    0x38db0826b852 @   12 : 28 f9 01 02       LdaNamedProperty r2, [1], [2]: Load a in the accumulator
    0x38db0826b856 @   16 : 26 fa             Star r1: Store accumulator in register 1
    0x38db0826b858 @   18 : 0b                LdaZero: Load 0 in accumulator
    0x38db0826b859 @   19 : 2a fb 04          LdaKeyedProperty r0, [4]: (presumibly) loading the property with key 4
                                                                        from the function frame with the accumulator
                                                                        (syncing) the argument here.
    0x38db0826b85c @   22 : 26 f8             Star r3: Store accumulator in register 3
    0x38db0826b85e @   24 : 59 fa f9 f8 06    CallProperty1 r1, r2, r3, [6]: console.log(r1)
    0x38db0826b863 @   29 : 0d                LdaUndefined: Load undefined in accumulator
    0x38db0826b864 @   30 : aa                Return: Return the accumulator value
Constant pool (size = 2)
Handler Table (size = 0)
Source Position Table (size = 0)
[为函数f(0x38db0826b679)生成的字节码]
参数计数2
寄存器计数4
帧大小32
0x38db0826b846@0:88 CreateUnmappedArguments
0x38db0826b847@1:26 fb Star r0:将累加器存储在寄存器0中(默认为函数帧指针)
0x38db0826b849@3:0c 63 LdaSmi[99]:在累加器中加载(SMallInteger)99
0x38db0826b84b@5:26 02星a0:将累加器存储在函数参数0中
0x38db0826b84d@7:13 00 LdaGlobal[0],[0]:我不知道
0x38db0826b850@10:26 f9星形r2:将累加器存储在寄存器2中
0x38db0826b852@12:28 f9 01 02 LdaNamedProperty r2[1],[2]:在蓄能器中加载a
0x38db0826b856@16:26 fa星形r1:将累加器存储在寄存器1中
0x38db0826b858@18:0b LdaZero:蓄能器中的负载为0
0x38db0826b859@19:2a fb 04 LdaKeyedProperty r0,[4]:(假定)正在使用键4加载属性
从带有蓄能器的功能框架
(同步)此处的参数。
0x38db0826b85c@22:26 f8星形r3:将累加器存储在寄存器3中
0x38db0826b85e@24:59 fa f9 f8 06 CallProperty1 r1、r2、r3[6]:console.log(r1)
0x38db0826b863@29:0d LdaUndefined:累加器中未定义负载
0x38db0826b864@30:aa返回:返回累加器值
固定池(大小=2)
处理程序表(大小=0)
震源位置表(大小=0)
这是我处理的第二个程序的输出:

[generated bytecode for function: f (0x3bd80826b679 <SharedFunctionInfo f>)]
Parameter count 2
Register count 4
Frame size 32
    0x3bd80826b846 @    0 : 88                CreateUnmappedArguments
    0x3bd80826b847 @    1 : 26 fa             Star r1: Store accumulator in register 1 (presumibly function frame pointer)
    0x3bd80826b849 @    3 : 25 02             Ldar a0: Load in the accumulator the argument 0
    0x3bd80826b84b @    5 : 9e 06             JumpIfNotUndefined [6] (0x3bd80826b851 @ 11): If accumulator is undefined:
    0x3bd80826b84d @    7 : 0c 37                 LdaSmi [55]: Load (SMallInteger) 55 in accumulator
    0x3bd80826b84f @    9 : 8b 04             Jump [4] (0x3bd80826b853 @ 13): else:
    0x3bd80826b851 @   11 : 25 02                 Ldar a0: Load argument 0 in accumulator
    0x3bd80826b853 @   13 : 26 fb             Star r0: Store accumulator in register 0
    0x3bd80826b855 @   15 : 0b                LdaZero: Load 0 in accumulator
    0x3bd80826b856 @   16 : 26 f8             Star r3: Store accumulator in register 3
    0x3bd80826b858 @   18 : 0c 63             LdaSmi [99]: Load (SMallInteger) 99 in accumulator
    0x3bd80826b85a @   20 : 30 fa f8 00       StaKeyedProperty r1, r3, [0]: (presumibly) loading in the function frame
                                                                            (r1) the value of the accumulator (99) in the
                                                                            property with key r3 (0) (syncing)
    0x3bd80826b85e @   24 : 13 00 02          LdaGlobal [0], [2]: (presumibly) loading the global value containing the
                                                                  pointer to a in the accumulator
    0x3bd80826b861 @   27 : 26 f8             Star r3: Store accumulator in register 3
    0x3bd80826b863 @   29 : 28 f8 01 04       LdaNamedProperty r3, [1], [4]: Load a in the accumulator
    0x3bd80826b867 @   33 : 26 f9             Star r2: Store accumulator in register 2
    0x3bd80826b869 @   35 : 59 f9 f8 fb 06    CallProperty1 r2, r3, r0, [6]: console.log(r2)
    0x3bd80826b86e @   40 : 0d                LdaUndefined: Load undefined in accumulator
    0x3bd80826b86f @   41 : aa                Return: Return the accumulator value
Constant pool (size = 2)
Handler Table (size = 0)
Source Position Table (size = 0)
[为函数f(0x3bd80826b679)生成的字节码]
参数计数2
寄存器计数4
帧大小32
0x3bd80826b846@0:88 CreateUnmappedArguments
0x3bd80826b847@1:26 fa星形r1:将累加器存储在寄存器1中(假定为函数帧指针)
0x3bd80826b849@3:25 02 Ldar a0:在累加器中加载参数0
0x3bd80826b84b@5:9e 06跳线未定义[6](0x3bd80826b851@11):如果累加器未定义:
0x3bd80826b84d@7:0c 37 LdaSmi[55]:累加器中的负载(小整数)55
0x3bd80826b84f@9:8b 04跳转[4](0x3bd80826b853@13):否则:
0x3bd80826b851@11:25 02 Ldar a0:累加器中的加载参数0
0x3bd80826b853@13:26 fb Star r0:将累加器存储在寄存器0中
0x3bd80826b855@15:0b LdaZero:蓄能器中的负载为0
0x3bd80826b856@16:26 f8星形r3:将累加器存储在寄存器3中
0x3bd80826b858@18:0c 63 LdaSmi[99]:在累加器中加载(SMallInteger)99
0x3bd80826b85a@20:30 fa f8 00 StaKeyedProperty r1,r3,[0]:(假定)在函数帧中加载
(r1)蓄能器(99)在
具有键r3(0)的属性(同步)
0x3bd80826b85e@24:13 00 02 LdaGlobal[0],[2]:(假定)正在加载包含
指向累加器中的
0x3bd80826b861@27:26 f8星形r3:将累加器存储在寄存器3中
0x3bd80826b863@29:28 f8 01 04 LdaNamedProperty r3[1],[4]:在蓄能器中加载a
0x3bd80826b867@33:26 f9星形r2:将累加器存储在寄存器2中
0x3bd80826b869@35:59 f9 f8 fb 06 CallProperty1 r2,r3,r0[6]:console.log(r2)
0x3bd80826b86e@40:0d LdaUndefined:累加器中未定义负载
0x3bd80826b86f@41:aa返回:返回累加器值
固定池(大小=2)
处理程序表(大小=0)
震源位置表(大小=0)
如您所见,第二段代码与第一段代码类似,添加了一条if语句来检查可选参数

最后,
deno中的
v8googleengine
10
打印两次。 这很奇怪,但我想这是有原因的。 可能是有人在实施过程中做出了这一决定,而不是每个人都反映了变化
[generated bytecode for function: f (0x38db0826b679 <SharedFunctionInfo f>)]
Parameter count 2
Register count 4
Frame size 32
    0x38db0826b846 @    0 : 88                CreateUnmappedArguments
    0x38db0826b847 @    1 : 26 fb             Star r0: Store accumulator in register 0 (presumibly function frame pointer)
    0x38db0826b849 @    3 : 0c 63             LdaSmi [99]: Load (SMallInteger) 99 in accumulator
    0x38db0826b84b @    5 : 26 02             Star a0: Store accumulator in function argument 0
    0x38db0826b84d @    7 : 13 00 00          LdaGlobal [0], [0]: I don't know
    0x38db0826b850 @   10 : 26 f9             Star r2: Store accumulator in register 2
    0x38db0826b852 @   12 : 28 f9 01 02       LdaNamedProperty r2, [1], [2]: Load a in the accumulator
    0x38db0826b856 @   16 : 26 fa             Star r1: Store accumulator in register 1
    0x38db0826b858 @   18 : 0b                LdaZero: Load 0 in accumulator
    0x38db0826b859 @   19 : 2a fb 04          LdaKeyedProperty r0, [4]: (presumibly) loading the property with key 4
                                                                        from the function frame with the accumulator
                                                                        (syncing) the argument here.
    0x38db0826b85c @   22 : 26 f8             Star r3: Store accumulator in register 3
    0x38db0826b85e @   24 : 59 fa f9 f8 06    CallProperty1 r1, r2, r3, [6]: console.log(r1)
    0x38db0826b863 @   29 : 0d                LdaUndefined: Load undefined in accumulator
    0x38db0826b864 @   30 : aa                Return: Return the accumulator value
Constant pool (size = 2)
Handler Table (size = 0)
Source Position Table (size = 0)
[generated bytecode for function: f (0x3bd80826b679 <SharedFunctionInfo f>)]
Parameter count 2
Register count 4
Frame size 32
    0x3bd80826b846 @    0 : 88                CreateUnmappedArguments
    0x3bd80826b847 @    1 : 26 fa             Star r1: Store accumulator in register 1 (presumibly function frame pointer)
    0x3bd80826b849 @    3 : 25 02             Ldar a0: Load in the accumulator the argument 0
    0x3bd80826b84b @    5 : 9e 06             JumpIfNotUndefined [6] (0x3bd80826b851 @ 11): If accumulator is undefined:
    0x3bd80826b84d @    7 : 0c 37                 LdaSmi [55]: Load (SMallInteger) 55 in accumulator
    0x3bd80826b84f @    9 : 8b 04             Jump [4] (0x3bd80826b853 @ 13): else:
    0x3bd80826b851 @   11 : 25 02                 Ldar a0: Load argument 0 in accumulator
    0x3bd80826b853 @   13 : 26 fb             Star r0: Store accumulator in register 0
    0x3bd80826b855 @   15 : 0b                LdaZero: Load 0 in accumulator
    0x3bd80826b856 @   16 : 26 f8             Star r3: Store accumulator in register 3
    0x3bd80826b858 @   18 : 0c 63             LdaSmi [99]: Load (SMallInteger) 99 in accumulator
    0x3bd80826b85a @   20 : 30 fa f8 00       StaKeyedProperty r1, r3, [0]: (presumibly) loading in the function frame
                                                                            (r1) the value of the accumulator (99) in the
                                                                            property with key r3 (0) (syncing)
    0x3bd80826b85e @   24 : 13 00 02          LdaGlobal [0], [2]: (presumibly) loading the global value containing the
                                                                  pointer to a in the accumulator
    0x3bd80826b861 @   27 : 26 f8             Star r3: Store accumulator in register 3
    0x3bd80826b863 @   29 : 28 f8 01 04       LdaNamedProperty r3, [1], [4]: Load a in the accumulator
    0x3bd80826b867 @   33 : 26 f9             Star r2: Store accumulator in register 2
    0x3bd80826b869 @   35 : 59 f9 f8 fb 06    CallProperty1 r2, r3, r0, [6]: console.log(r2)
    0x3bd80826b86e @   40 : 0d                LdaUndefined: Load undefined in accumulator
    0x3bd80826b86f @   41 : aa                Return: Return the accumulator value
Constant pool (size = 2)
Handler Table (size = 0)
Source Position Table (size = 0)