事出有因
今天去做瞭金山網絡招聘實習生的試卷,有一道題目確實讓我有點在當時不太肯定,畢竟自己的腦袋還不是javascript解析器,然後回來就打開chrome的控制臺,運行後就覺得自己要去總結這個知識點瞭。
題目如下(隻能說大概,有點忘記,但是考察知識點是一樣)
- function foo(a,b,c){
- c = 3;
- console.log(arguments);
- }
- foo(1,2)
-
foo(1,2,undefined)
確實當時看見這道題目的時候,心裡還是有很多疑問的,最後隻能歸結成一個是arguments對象是什麼時候才賦值?
瞭解arguments
arguments的基本信息1 它不是真正的數組,隻是一個類數組的對象,具體兩者有什麼區別,這個不是我們這篇文章瞭解的重點;2 它創建於函數定義,並設置為null,賦值於函數調用,它是一個指向函數的參數列表的引用,是函數體訪問形參的接口3 它隻能作用於該函數的函數體,在外界訪問這個對象會出錯或者隻是nullarguments奇葩行為1 因為它是類數組的對象,它具有一個length屬性還有就是可以用下標來訪問參數列表2 因為它是函數的屬性,如果你在函數體中重新定義一個arguments變量,它會覆蓋原來的arguments
代碼:
- function foo(a,b,c){
- var arguments = 1;
- console.log(arguments);
- }
-
foo(1,2)
結果:1
3 在非嚴格的情況下,我們可以通過arguments來修改參數列表
代碼:
- function foo(a,b,c){
- arguments[0] = “monkindey”;
- console.log(a);
- }
-
foo(1,2)
結果:”monkindey”
那好吧,我們還是揭秘金山實習生招聘的筆試題
foo(1,2)答案:[1,2]
原因:arguments標示符在《javascript權威指南》中指出,它是指向實參對象的引用。實參對象是一個類數組,當實參對象改,那麼arguments也會跟著改。而實參對象隻有在函數調用時才賦值,比如上面實參對象就類似於{a:1,b:2},但是沒有c,所以給c賦值,改變不瞭實參對象,而arguments是它的引用,所以它也沒影響。foo(1,2,undefined)答案:[1,2,3]
原因:實參對象會是{a:1,b:2,c:undefined},而在函數體中再修改c的話,就會設置實參對象中的c為3。所以console.log(arguments)會變成[1,2,3]再練練兵
函數內部聲明的局部變量與形參同名
- function foo(a,b,c){
- var a = 3;
- console.log(arguments[0]);
- }
-
foo(1,2)
答案:3
原因:個人覺得當我們調用一個函數,傳入進去的實參,就是給一個函數中的形參賦值,其實相當於在函數定義一個局部變量,變量名就是那個形參名,上面的代碼可以看成- function foo(a,b,c){
- var a = 1;//傳入實參的形參相當於在函數體中定義一個局部變量
- var a = 3;
- console.log(arguments[0]);
- }
-
foo(1,2)
如果隻是聲明局部變量a,卻不賦值,情況又不一樣瞭- function foo(a,b,c){
- var a ;
- console.log(arguments[0]);
- }
-
foo(1,2)
答案:1
原因:上面的代碼可以看成- function foo(a,b,c){
- var a = 1;//傳入實參的形參相當於在函數體中定義一個局部變量
- var a ;//重復定義一個變量但是又不賦值,javascript解析器會把它忽略掉的(我的猜想)
- console.log(arguments[0]);
- }
-
foo(1,2)
參考文獻
arguments MDN
《javascript權威指南》
JavaScript函數參數的可修改性