JavaScript里面的arguments到底是個啥?


類數組對象:arguments

總所周知,js是一門相當靈活的語言。當我們在js中在調用一個函數的時候,我們經常會給這個函數傳遞一些參數,js把傳入到這個函數的全部參數存儲在一個叫做arguments的東西里面,那么這到底是什么東西?

在js中萬物皆對象,甚至數組字符串函數都是對象。所以這個叫做arguments的東西也是個對象,而且是一個特殊的對象,它的屬性名是按照傳入參數的序列來的,第1個參數的屬性名是’0’,第2個參數的屬性名是’1’,以此類推,並且它還有length屬性,存儲的是當前傳入函數參數的個數,很多時候我們把這種對象叫做類數組對象。類數組對象和數組都是對象這個媽生的,但是數組是大哥比類數組對象多了很多其他的玩具(方法),類數組對象只是長得很像數組的弟弟而已。

慢着,剛剛不是說數組也是對象嗎,現在這個類數組對象又是什么? 沒辦法,js就是這么的靈活。這個類數組對象不僅存儲給函數傳入的參數,也具有一些其他的屬性,等下會一一道來。

因為類數組對象和數組有很多的共性,所以我們經常可以用call方法,讓類數組對象也使用的數組的一些方法,就是讓這個弟弟去玩哥哥的玩具,比如……,還是不扯遠了,這篇文章只是說什么是arguments,想知道更多關於對象如何借調數組方法的話,請參考這篇文章。


arguments的屬性
接下來我們來看看arguments對象里面到底有些什么東西,是騾子是馬拉出來溜溜。

1 function showargs() { 2  console.log( arguments ); 3 } 4 5 showargs(1,2,3,4,5);

下面我們用console.log的方式,將arguments對象輸出到控制台,這里不得不說一句,chrome的console工具好用得不得了(我不是來打廣告的)。



這里我們可以看到arguments對象將我傳入的五個參數以數組的形式保存在里面,還有保存了我傳入函數的實參的個數(length)。而且我們可以看到arguments對象的 ==_ proto _== 是指向object的,這也說明了他是個類數組對象,而不是一個數組。

有了這個對象我們以后寫函數的時候,就不用給所有的形參指定參數名,然后通過參數名的方式獲取參數了,我們可以直接使用arguments對象來獲取實參,這樣是不是方便了很多呢。
有些語言在我們給函數指定了參數名之后,當調用函數時,會判斷當前傳入的參數是否與函數定義的參數個數相等,不相等就會報錯,但是靈活的js(不是我說,js是真的靈活)並不會驗證傳遞給函數的參數個數是否等於函數定義的參數個數。所以為了裝逼(代碼的簡潔度),我們使用arguments調用參數可以不混淆不同函數之間的參數名。另外為了裝逼(代碼的嚴整度),我們也能用arguments來判斷當前傳入參數的個數是否與我們需要的數量一致。

下面舉個栗子:

 1 function add() {
 2     if( arguments.length == 2 ){
 3         return arguments[0] + arguments[1];
 4     }else{
 5         return '傳入參數不合法';
 6     }
 7 }
 8 
 9 console.log( add(2,3) );
10 console.log( add(1,2,3) );

看看結果:


最后我們還可以看到arguments還有一個叫做callee的屬性,這個屬性是表示的是當前函數的一個引用,簡單點說,這個屬性里面存儲的我們調用的這個函數的代碼,實在無法理解的時候,又到了console.log大顯身手的時候了。

 1 function showcallee() {
 2     var a = '這里是代碼';
 3     var b = '這是另一段代碼';
 4     var c = a + b;
 5 
 6     console.log(arguments.callee);
 7 
 8     return c;
 9 }
10 showcallee();

結果



看到結果的你是不是和我一樣驚呆了呢,這不就是我寫的代碼嗎,arguments.callee完完整整的把這個函數的這段代碼返回了。
arguments的一些妙用

1.利用arguments實現方法的重載

下面我們利用arguments對象來實現一個參數相加的函數,不論傳入多少參數都行,將傳入的參數相加后返回。

 1 function add() {
 2     var len = arguments.length,
 3         sum = 0;
 4     for(;len--;){
 5         sum += arguments[len];
 6     }
 7     return sum;
 8 }
 9 console.log( add(1,2,3) );   //6
10 console.log( add(1,3) );     //4
11 console.log( add(1,2,3,5,6,2,7) );   //26

由於js是一種弱類型的語言,沒有重載機制,當我們重寫函數時,會將原來的函數直接覆蓋,這里我們能利用arguments,來判斷傳入的實參類型與數量進行不同的操作,然后返回不同的數值。

2.利用arguments.callee實現遞歸

先來看看之前我們是怎么實現遞歸的,這是一個結算階乘的函數

1 function factorial(num) {
2     if(num<=1) {
3         return 1;
4     }else {
5         return num * factorial(num-1);
6     }
7 } 

但是當這個函數變成了一個匿名函數時,我們就可以利用callee來遞歸這個函數。

1 function factorial(num) {
2     if(num<=1) {
3         return 1;
4     }else {
5         return num * arguments.callee(num-1);
6     }
7 } 


這個方法雖然好用,但是有一點值得注意,ECMAScript4中為了限制js的靈活度,讓js變得嚴格,新增了嚴格模式,在嚴格模式中我們被禁止不使用var來直接聲明一個全局變量,當然這不是重點,重點是arguments.callee這個屬性也被禁止了。不過這都不是事兒,ES6為我們新增了很多好用的變量聲明方式和新的語法糖,作為一個時髦的前端,我們趕緊學習一些ES6的新語法吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM