首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用参数数组更改JavaScript函数的参数值

使用参数数组更改JavaScript函数的参数值
EN

Stack Overflow用户
提问于 2019-01-23 08:39:26
回答 6查看 7.1K关注 0票数 36

我正在学习JavaScript,对arguments属性数组非常困惑。

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

代码语言:javascript
运行
复制
function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(1)); //returns 2

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

代码语言:javascript
运行
复制
function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a()); //returns undefined

但是即使我通过了undefined,这个值也会更新。

代码语言:javascript
运行
复制
function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(undefined)); //returns 2

我认为,如果不将参数传递给JavaScript函数,它会自动创建该参数并将其赋值给undefined,更新后它应该会反映更新后的值,对吗?

a()a(undefined)也是一样的,对吧?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2019-01-23 08:59:28

分配给arguments索引只会更改相关的参数值(让我们称它为n-th参数),如果函数至少使用n参数调用。arguments对象的数值索引属性本质上是设置器(和getter):

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

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

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

  1. len是args中的元素数。
  2. indx = len - 1
  3. indx >= 0**,** (因此,当没有参数传递给函数时,下面的循环将不会运行)。)

(为正在创建的参数对象赋值,这里称为map__:)

    1. 添加name作为列表mappedNames的一个元素。

    1. g是使用参数nameenv调用MakeArgGetter抽象操作的结果。

    1. p是使用参数nameenv调用MakeArgSetter抽象操作的结果。

    1. 调用map传递ToString(indx)的[Get]内部方法,属性描述符{[Set]:p,[Get]:g,[Configurable]:true}和false作为参数。

因此,如果函数是在没有参数的情况下调用的,那么arguments[0]上就不会有一个setter,因此重新分配它将不会更改索引0处的参数。

同样的情况也发生在其他指示符中--如果调用一个带有1个参数的函数,但该函数接受两个参数,则分配给arguments[1]不会更改第二个参数,因为arguments[1]没有一个setter:

代码语言:javascript
运行
复制
function fn(a, b) {
  arguments[1] = 'bar';
  console.log(b);
}
fn('foo');

所以

a()a(undefined)是一回事,对吗?

情况并非如此,因为第二个结果是索引0上带有setter和getter的arguments对象,而第一个则不是。

请注意,arguments和函数参数之间的这种奇怪的交互作用只存在于草率模式中。在严格模式下,对arguments的更改不会对单个参数标识符包含的值产生任何影响:

代码语言:javascript
运行
复制
'use strict';
function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(1)); //returns 1

票数 24
EN

Stack Overflow用户

发布于 2019-01-23 08:45:59

ECMA 262 9.0 20189.4.4参数--外来对象中描述这种行为

附注1: 参数外来对象的整数索引数据属性,其数值名称值小于对应功能对象的形式参数数,其值最初与函数的执行上下文中的相应参数绑定共享它们的值。这意味着更改属性将更改参数绑定的相应值,反之亦然。如果删除该属性,然后重新定义该属性,或者将该属性更改为存取性质,则会中断此对应关系。如果参数对象是普通对象,则其属性值只是传递给函数的参数的副本,而且属性值与形式参数值之间没有动态链接。

总之,

  • 如果在'sloppy mode'中,那么所有参数都映射到它们的命名变量,如果长度对应于给定的参数,或者
  • 如果在'strict mode'中,那么在传递参数之后绑定就会丢失。

这仅在较早版本的ECMA 262 7.0 2016中可读。它在9.4.4参数--外来对象中描述这种行为

附注1: 对于非严格函数,参数对象的整数索引数据属性,其数值名称值小于对应函数对象的形式参数数,最初在函数的执行上下文中与相应的参数绑定共享它们的值。这意味着更改属性将更改参数绑定的相应值,反之亦然。如果删除该属性,然后重新定义该属性,或者将该属性更改为访问器属性,则此对应关系将中断。对于严格的模式函数,参数对象属性的值只是传递给函数的参数的副本,在属性值和形式参数值之间没有动态联系。

票数 7
EN

Stack Overflow用户

发布于 2019-01-23 08:50:14

这是因为参数不像Array,它是一个具有整数索引数据键和属性长度的对象,如果长度等于零,就意味着没有参数

代码语言:javascript
运行
复制
function a(b) {
    arguments[0] = 2;
    console.log(arguments.length) 
    return b;
}
a(1); // length 1  returns 2
console.log(a());  // length 0  returns undefined

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54323086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档