使用参数数组更改JavaScript函数的参数值无效

Ami*_*Das 36 javascript arrays arguments function variable-assignment

我正在学习JavaScript,我对arguments属性数组感到很困惑.

我有一个函数,它接受一个参数并返回它.当我传递参数并使用arguments[0] = value它重新分配时,它正在更新值.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(1)); //returns 2
Run Code Online (Sandbox Code Playgroud)

但是当我调用没有参数的相同函数时它返回undefined.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a()); //returns undefined
Run Code Online (Sandbox Code Playgroud)

但即使我通过undefined,价值也会更新.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(undefined)); //returns 2
Run Code Online (Sandbox Code Playgroud)

我认为如果你没有将参数传递给JavaScript函数,它会自动创建它并分配值,undefined并在更新后它应该反映更新的值,对吧?

a()a(undefined)是相同的东西,对不对?

Cer*_*nce 24

如果使用至少参数调用函数,则分配给arguments标记只会更改关联的参数值(让我们将其称为n-th参数)n.该arguments对象的数字索引的性能基本上是setter方法(和getter方法):

http://es5.github.io/#x10.6

下面的斜体是我对该过程与该问题的关系的评论:

(设)args(是)传递给[[Call]]内部方法的实际参数

  1. lenargs中的元素个数.

  2. indx= len - 1.

  3. 重复同时indx >= 0,(因此,下面的循环不会在没有参数传递给函数运行:)

(分配给对象所创建的参数,这里所说的map:)

    1. 添加name为列表的元素mappedNames.
    1. 让我们用参数和g调用MakeArgGetter抽象操作的结果.nameenv
    1. 让我们用参数和p调用MakeArgSetter抽象操作的结果.nameenv
    1. 调用[[DefineOwnProperty]]内部方法map传递ToString(indx),属性描述符{[[Set]]:p,[[Get]]:g,[[Configurable]]:true},并false作为参数.

因此,如果在没有参数的情况下调用该函数,则不会启用setter arguments[0],因此重新分配它不会更改索引0处的参数.

对于其他指标也会出现同样的情况 - 如果您使用1个参数调用函数,但该函数接受两个参数,则分配arguments[1]将不会更改第二个参数,因为arguments[1]没有setter:

function fn(a, b) {
  arguments[1] = 'bar';
  console.log(b);
}
fn('foo');
Run Code Online (Sandbox Code Playgroud)

所以

a()并且a(undefined)是一回事吗?

情况并非如此,因为第二个导致一个arguments对象在索引0上有一个setter和一个getter,而第一个没有.

  • 无论如何定义`arguments`对象,几乎任何对象都可以随意分配任何属性.例如,`const foo = {}; foo [0] ='bar';`.当你的`a`被调用而没有参数时,这类似于你的`arguments [0] = 2` - 索引0上没有setter或getter,所以你可以毫无问题地分配它,它不会抛出错误,但它不会影响其他任何事情. (2认同)
  • 我懂了。谢谢。哇 JavaScript 很奇怪。 (2认同)

Nin*_*olz 6

ECMA 262 9.0 2018介绍了此行为 9.4.4参数外来物体

注1:

数据名称值小于相应函数对象的形式参数数量的参数奇异对象的整数索引数据属性最初与函数执行上下文中的相应参数绑定共享其值.这意味着更改属性会更改参数绑定的相应值,反之亦然.如果删除并重新定义此属性或将属性更改为存取属性,则此对应关系将被破坏.如果arguments对象是普通对象,则其属性的值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接.

简而言之,

  • 如果在'sloppy mode',则所有参数都映射到它们的命名变量,如果长度对应于给定的参数,或者

  • if in 'strict mode',然后在移交参数后丢失绑定.

这仅适用于旧版ECMA 262 7.0 2016.它描述了这种行为9.4.4参数外来物体

注1:

对于非严格函数,参数对象的整数索引数据属性(其数字名称值小于相应函数对象的形式参数的数量)最初与函数执行上下文中的相应参数绑定共享其值.这意味着更改属性会更改参数绑定的相应值,反之亦然.如果删除并重新定义此属性或将属性更改为存取属性,则此对应关系将被破坏.对于严格模式函数,arguments对象的属性值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接.