简体   繁体   English

为什么JavaScript Arguments对象通过赋值给参数而变异?

[英]Why are JavaScript Arguments objects mutated by assignment to parameter?

What is the rationale behind this behaviour? 这种行为背后的理由是什么?

function f(x) {
  console.log(arguments[0]);
  x = 42;
  console.log(arguments[0]);
}

f(1);
// => 1
// => 42

Perhaps this was a genuine mistake. 也许这是一个真正的错误。 Which section of the ECMAScript specification defines this behaviour? ECMAScript规范的哪个部分定义了这种行为?

Actually, in strict mode, this does not happen as you can see here . 事实上,在严格模式下,这不会发生,因为你可以在这里看到

If you read section 10.6 of the ECMA Standard , in particular Note 1, you'll see: 如果您阅读ECMA标准的第10.6节,特别是注1,您会看到:

For non-strict mode functions the array index (defined in 15.4) named data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function's execution context. 对于非严格模式函数,数组索引(在15.4中定义)命名数据属性的参数对象,其数字名称值小于相应函数对象的形式参数的数量,最初与函数的相应参数绑定共享它们的值。执行上下文。 This means that changing the property changes the corresponding value of the argument binding and vice-versa. 这意味着更改属性会更改参数绑定的相应值,反之亦然。 This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. 如果删除并重新定义此属性或将属性更改为存取属性,则此对应关系将被破坏。 For strict mode functions, the values of the arguments object's properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values. 对于严格模式函数,arguments对象的属性值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接。

In short, what this is saying is that, in non-strict mode, named function parameters operate as aliases for items in the arguments object. 简而言之,这就是说,在非严格模式下,命名函数参数作为arguments对象中项目的别名。 Thus, changing the value of a named parameter will change the value of the equivalent arguments item and vice versa. 因此,更改命名参数的值将更改等效arguments项的值,反之亦然。 This is not a mistake. 这不是一个错误。 This is expected behaviour. 这是预期的行为。

As an editorial, it's probably not a good idea to rely on this behaviour as it can lead to some very confusing code. 作为一篇社论,依靠这种行为可能不是一个好主意,因为它可能会导致一些非常混乱的代码。 Also, such code, if executed in strict mode, would not longer work. 此外,如果在严格模式下执行此类代码将不再有效。

Altering x is reflected in arguments[0] because indexes of arguments may be getter/setters for the matching named argument. 改变x反映在arguments[0]因为arguments索引可能是匹配命名参数的getter / setter This is defined under step 11.c.ii of 10.6 : 这是在10.6的步骤11.c.ii中定义

  1. Add name as an element of the list mappedNames . 添加名称作为列表mappedNames的元素。

  2. Let g be the result of calling the MakeArgGetter abstract operation with arguments name and env . g是使用参数nameenv调用MakeArgGetter抽象操作的结果。

  3. Let p be the result of calling the MakeArgSetter abstract operation with arguments name and env . p是使用参数nameenv调用MakeArgSetter抽象操作的结果。

  4. Call the [[DefineOwnProperty]] internal method of map passing ToString (indx), the Property Descriptor {[[Set]]: p , [[Get]]: g , [[Configurable]]: true }, and false as arguments. 调用传递给ToString (indx)的地图的[[DefineOwnProperty]]内部方法, 属性描述符 {[[Set]]: p ,[[Get]]: g ,[[Configurable]]: true },并将false作为参数。

As noted in the steps above that, this requires that strict is false and, in this case, that f is called with a value for x : 如上面的步骤所述,这要求strict false ,在这种情况下, fx的值调用:

f()  // undefined, undefined (no argument, no getter/setter)
f(1) // 1, 42

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

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