Javascript中的参数和参数之间的联系是什么

what is the link between arguments and parameters in Javascript?

本文关键字:参数 联系 是什么 之间 Javascript      更新时间:2023-09-26
<!DOCTYPE HTML>
<html>
<body>
<script>
sayHi(1,2,3)
function sayHi(x,y,z) {
    alert("1:"+arguments[0]);// alert 1 as expected
    alert("2:"+arguments[1]);// alert 2 as expected
    alert("3:"+arguments[2]);// arert 3 as expected
    [].shift.call(arguments); 
    [].shift.call(arguments); 
    [].shift.call(arguments); 
    alert("4:"+x);           // alear 3, why?? :/  
    alert("5:"+y);           // alert 3, why?? :/  
    alert("6:"+z);           // alert 3, why?? :/  
    alert("7:"+arguments[0]);           // undefined, no x any more :/  
    alert("8:"+arguments[1]);           // undefined, no y any more :/  
    alert("9:"+arguments[2]);           // undefined, no z any more :/  
 }
</script>
</body>
</html>

我知道每个函数中都有一个特殊的伪数组,称为参数。上面的代码移动了参数的第一个元素,但是当我尝试提醒参数 x,y,z 的值时,所有值都是 3 而不是未定义。如果参数和参数之间存在链接,那么参数[0] -> x,参数[1]->y,arugments[2]->z,参数[0],参数[1],参数[2]如何都变得未定义,而参数x,y,z都是3??

Javascript中的参数和参数之间的联系是什么?我知道每个函数中都有一个特殊的伪数组,称为参数。

是的。在草率模式下,分配给它是特殊的 - 每个属性(012(都是对该序数命名参数的getter/setter引用。

这意味着当你分配给x时,arguments[0]也将具有该值。当你赋值给arguments[0]时,x变量也会得到这个值。

因此,为了解释您的代码段,我们需要确定shift.call的作用。规范告诉我们:它将所有值移动到开头,删除最后一个索引,并递减.length。因此,让我们将其重写为:

sayHi(1, 2, 3);
function sayHi(x,y,z) {
/*  var x = 1,
        y = 2,
        z = 3,
    arguments = {
        get 0() { return x }, set 0(v) { x = v },
        get 1() { return y }, set 1(v) { y = v },
        get 2() { return z }, set 2(v) { z = v },
        length: 3
    }
*/
    //  variables   arguments
    //  x   y   z  [0] [1] [2] length
    //  1   2   3   1   2   3   3
    // [].shift.call(arguments):
    arguments[0] = arguments[1]; arguments[1] = arguments[2]; delete arguments[2]; arguments.length--;
//  x = 2;                       y = 3;
    //  2   3   3   2   3   -   2
    [].shift.call(arguments);
    // [].shift.call(arguments):
    arguments[0] = arguments[1]; delete arguments[1]; arguments.length--;
//  x = 3;
    //  3   3   3   3   -   -   1
    // [].shift.call(arguments):
    delete arguments[0]; arguments.length--;
//  ;
    //  3   3   3   -   -   -   0
}

如您所见,当shift重新分配arguments的索引(并调用 setter(时,这反映在相应的参数变量中。但是,当您delete属性时,不会调用 setter,也不会修改变量 - 无论如何您都无法"取消声明"变量。

这仅适用于没有严格模式:

function test(x, y) {
  console.log("Original: " + x); // 1
  [].shift.apply(arguments);
  console.log("Modified: " + x); // 2
}
function testStrict(x, y) {
  "use strict"
  console.log("Original (strict): " + x); // 1
  [].shift.apply(arguments);
  console.log("Modified (strict): " + x); // 1
} 

test(1,2)
testStrict(1,2)

http://jsfiddle.net/omahlama/mmn2vf0p/