2014-11-03 84 views
1
<!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中参数和参数之间的链接是什么?

+2

有趣的事实:除非他们不成为未定义的实际命名的参数得到与他们的参数数组中的位置有关。所以如果你转移到左边,只有在它们没有变成未定义的时候才会覆盖这些值。你可以通过只移动一次来检查这一点,然后你看到x变成了2,y变成了3,z留下了3.有趣的事情这个javascript;) – Markai 2014-11-03 11:47:01

+0

@Markai谢谢,我再次阅读你的评论,我发现你回答了我的问题!再次感谢! – bean 2014-11-05 11:06:26

回答

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/

1

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

是的。而在马虎模式,分配给它特殊的 - 每个属性(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指数(并调用二传手),这反映在相应的参数变量。但是,如果您使用delete属性,那么setter不会被调用,并且变量也不会被修改 - 您无论如何都不能“undeclare”一个变量。

+0

thx,但你没有告诉我为什么x,y,z变成1,2,3 - > 3,3,3?作为参数[0],参数[1],参数[2]是 - - - ,那么为什么x,y,z是3,3,3? – bean 2014-11-05 10:58:05

+1

因为当'arguments'属性被删除时,变量不会被修改 - setter属性不会被调用。如果'shift'将会被赋值*'undefined',那么这些变量就会反映出来。 – Bergi 2014-11-05 13:36:24

+0

谢谢,现在我明白了。 – bean 2014-11-05 14:26:00

相关问题