繁体   English   中英

为什么默认 arguments 在 javascript 中的 function 内部是不可变的?

[英]Why default arguments are immutable inside of a function in javascript?

为什么在 javascript 中,默认的 arguments 不能在 function 内部更改,而非默认的可以?

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

对比

function func(a = 55) {
  arguments[0] = 99; // updating arguments[0] does not also update a
  console.log(a);
}
func(10); // prints 10

查看MDN Web 文档

Non-strict functions that are passed only simple parameters (that is, not rest, default, or restructured parameters) will sync the value of variables new values in the body of the function with the arguments object, and vice versa:

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

并且

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

Conversely, non-strict functions that are passed rest, default, or destructured parameters will not sync new values assigned to argument variables in the function body with the arguments object. Instead, the arguments object in non-strict functions with complex parameters will always reflect the values passed to the function when the function was called (this is the same behavior as exhibited by all strict-mode functions, regardless of the type of variables they are通过):

function func(a = 55) {
  arguments[0] = 99; // updating arguments[0] does not also update a
  console.log(a);
}
func(10); // 10

function func(a = 55) {
  a = 99; // updating a does not also update arguments[0]
  console.log(arguments[0]);
}
func(10); // 10

并且

// 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)

这是我处理的第二个程序的 output:

[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)

如您所见,第二个代码看起来像第一个,添加了一个 if 语句来检查可选参数。

最后, deno中的v8 google engine打印了10两次。 这很奇怪,但我认为发生这种情况是有原因的。 可能有人在他们的实施中做出了这个决定,并不是每个人都反映了这个变化。 但是,请不要烤我,我尽力在没有手册的情况下理解字节码,所以如果有错误,请告诉我,我会修复它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM