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

时间:2014-11-03 11:41:31

标签: javascript arguments

<!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而不是undefined。如果参数和参数之间存在链接,则参数[0] - &gt; x,arguments [1] - &gt; y,arugments [2] - &gt; z,如果参数x,y,z都是3,参数[0],参数[1],参数[2]如何变为未定义? ?

2 个答案:

答案 0 :(得分:1)

  

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

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

这意味着当您分配到x时,arguments[0]也会拥有该值。当您分配到arguments[0]时,x变量也会获得该值。

因此,要解释您的代码段,我们需要确定shift.call的作用。 The spec告诉我们:它将所有值一个移到开头,删除最后一个索引,然后递减.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,并且不会修改变量 - 您不能&#34; undeclare&#34;无论如何都是一个变量。

答案 1 :(得分:0)

这只适用于没有严格模式的情况:

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/