Javascript中参数和参数之间的链接是什么?
问题描述:
<!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而不是未定义的。如果参数和参数之间存在关联,那么arguments [0] - > x,arguments [1] - > y,arugments [2] - > z,参数[0],参数[1],参数[2]全部变得不确定,而参数x,y,z都是3?Javascript中参数和参数之间的链接是什么?
答
这只能没有严格的模式:
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)
答
什么是在Javascript参数和参数之间的联系?我知道每个函数里面都有一个称为参数的特殊伪数组。
是的。而在马虎模式,分配给它特殊的 - 每个属性(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
指数(并调用二传手),这反映在相应的参数变量。但是,如果您使用delete
属性,那么setter不会被调用,并且变量也不会被修改 - 您无论如何都不能“undeclare”一个变量。
有趣的事实:除非他们不成为未定义的实际命名的参数得到与他们的参数数组中的位置有关。所以如果你转移到左边,只有在它们没有变成未定义的时候才会覆盖这些值。你可以通过只移动一次来检查这一点,然后你看到x变成了2,y变成了3,z留下了3.有趣的事情这个javascript;) – Markai 2014-11-03 11:47:01
@Markai谢谢,我再次阅读你的评论,我发现你回答了我的问题!再次感谢! – bean 2014-11-05 11:06:26