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

更改JavaScript函数';使用参数数组的s参数值无效,javascript,arrays,function,arguments,variable-assignment,Javascript,Arrays,Function,Arguments,Variable Assignment,我正在学习JavaScript,对参数属性数组感到非常困惑 我有一个函数,它接受一个参数并返回它。当我传递参数并使用参数[0]=value重新分配它时,它正在更新值 功能a(b){ 参数[0]=2; 返回b; } 控制台日志(a(1))//返回2在中描述此行为 注1: 参数对象的整数索引数据属性(其数值名称值小于相应对象的形式参数数)最初与函数中的相应参数绑定共享其值。这意味着更改属性会更改参数绑定的相应值,反之亦然。如果删除并重新定义该属性,或者将该属性更改为新属性,则会破坏此对应关系。如果

我正在学习JavaScript,对
参数
属性数组感到非常困惑

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

功能a(b){
参数[0]=2;
返回b;
}
控制台日志(a(1))//返回2
在中描述此行为

注1:

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

总之,

  • 如果处于
    “sloppy模式”
    ,则所有参数都映射到其命名变量(如果长度对应于给定参数),或者

  • 如果处于
    “严格模式”
    ,则在移交参数后绑定将丢失

这仅在较旧版本的中可读。它使用

注1:

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


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

功能a(b){
参数[0]=2;
console.log(arguments.length)
返回b;
}
a(1);//长度1返回2

console.log(a());//长度0返回未定义的
我的理解是arguments对象只跟踪传递到函数中的内容。由于您最初没有传递任何内容,
b
没有绑定,此时
arguments
没有“跟踪”
b
。接下来,将一个值赋给初始化但为空的类似数组的对象
arguments
,最后返回未定义的b

要进一步深入研究这一点:

如果非严格函数不包含rest、default或destructured参数,则arguments对象中的值会与参数变量的值同步更改。请参阅下面的代码:

如果非严格函数确实包含rest、default或destructured参数,则arguments对象中的值不会跟踪参数的值。相反,它们反映了调用函数时提供的参数:


来源:

当您不提供任何参数时,
参数
数组的
长度
等于0。然后您试图将数组中不存在的元素设置为
2
,这将导致返回未定义

您可以使用以下代码段简单地测试这一点:

function a(b){ 
    alert(arguments.length) // It will prompt 0 when calling a() and 1 when calling a(undefined)
    arguments[0] = 2; 
    return b; 
}

这是javascript规范中未定义的值定义:

未为变量赋值时使用的原语值。

因此,如果不指定函数返回类型,它将返回undefined

所以a()和a(未定义)不是一回事。返回未定义取决于返回类型是否已定义


更多说明

如果函数调用时至少有
n个
参数,则赋值给
参数
只会更改相关的参数值(我们称之为
n
-th参数)。
参数
对象的数字索引属性本质上是setter(和getter):

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

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

  • len
    为args中的元素数

  • indx
    =
    len-1

  • indx>=0
    时重复该操作(因此,当没有参数传递给函数时,下面的循环将不会运行:)

  • (分配给正在创建的arguments对象,此处称为
    map
    :)

    • 添加
      name
      作为列表的元素
      mappedNames
    • g
      成为使用参数
      name
      env
      调用
      MakeArgGetter
      抽象操作的结果
    • p
      成为使用参数
      name
      env
      调用
      MakeArgSetter
      抽象操作的结果
    • 调用
      map
      传递到字符串(
      indx
      )的[[DefineOwnProperty]]内部方法,属性描述符{[[Set]]:
      p
      ,[[Get]]:
      g
      ,[[Configurable]]:
      true
      ,以及
      false
      作为参数
    那么,如果函数
    function func(a) { 
      a = 99; // updating a also updates arguments[0]
      console.log(arguments[0]);
    }
    func(10); // 99
    
    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
    
    function a(b){ 
        alert(arguments.length) // It will prompt 0 when calling a() and 1 when calling a(undefined)
        arguments[0] = 2; 
        return b; 
    }