<!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]如何变为未定义? ?
答案 0 :(得分:1)
Javascript中参数和参数之间的联系是什么?我知道每个函数里面都有一个特殊的伪数组,叫做arguments。
是。在草率模式下,对它的赋值是特殊的 - 每个属性(0
,1
,2
)都是对该序数的命名参数的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)