2014-11-03 29 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

相關問題