前言
我最近在思考一個問題,我本身平時還是積累了不少東西,面試時候問的東西基本逃不出寫的博客(當然,高級階段的就不行了),但是真的被問到時我卻不一定答得上來。
知道且能回答,回答的效果都不是很好。。。。這是一個讓人很囧的事情,另外,按道理說阿里面試是完蛋了,后面再慢慢找工作吧,休息一下也不錯的。
除了記憶力意外,心態也是一個問題,比如我最常說的一句話就是:
恩,你說這個我知道,我還特意學習過,寫了demo,但是給忘了!!!
哎喲,我聽到這句話都可恥的笑了,你忘了和我有一毛線關系?忘了是很多原因造成的,最直接原因應該是不夠深刻,所以最近我們便拋開其它雜念,由最基礎的HTML+CSS+Javascript學習吧。
這次學習,希望能給各位以及自己帶來不一樣的感覺,由於最近要出去面試,問的最多的恐怕是javascript,所以我們先看看js了,這次學習中我把一些平時了解得似是而非的東西都給揪出來看看。
函數參數
各位看得沒錯,我覺得我對函數的參數理解不夠徹底,各位怎么樣呢,我現在出個例子來試試:
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(d) { 3 for (var k in d) { 4 alert(k + ': ' + d[k]); 5 } 6 } 7 alertArgurment(param);
這個題自然沒有問題,那我們變化一下呢?
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(param) { 3 for (var k in param ) { 4 alert(k + ': ' + param [k]); 5 } 6 } 7 alertArgurment(param);
各位現在知道自己使用的是外面的param還是里面的param呢?若是仍然難不倒你,看看這個呢:
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(d) { 3 param.id = '刀狂劍痴'; 4 for (var k in d) { 5 alert(k + ': ' + d[k]); 6 } 7 } 8 alertArgurment(param);
那么這個呢?或者說這段代碼與這段代碼有什么不同呢?請對比兩段代碼:
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(d) { 3 d.id = '刀狂劍痴'; 4 for (var k in d) { 5 alert(k + ': ' + d[k]); 6 } 7 } 8 alertArgurment(param);
怎么樣呢?對於參數各位還敢說知道嗎,我反正有點不敢了,於是再看看各位知道下面這些家伙是干什么的嗎?
① arguments
② callee
③ caller
若是你都知道並且了解十分深入的話,那么我又在自己為難自己了。。。。好了,上面的問題先留着,我們來看看什么是參數:
ECMAScript函數的參數與其它語言有所不同,其有以下特點:
① 個數不限
② 類型不限
③ 函數調用時候參數傳遞看心情
ECMAScript在內部是使用一個數組來表示參數的:arguments對象可訪問這個數組。
但是arguments只是與數組類似,他並不是Array的實例,所以我們定義函數時候可以不顯示定義參數而是使用arguments[0]的方式讀取
於是函數重載什么的也只能是傳說了。
callee:函數內部有兩個特殊對象,一個是this一個是arguments,其中arguments有一個callee的屬性,他是一個指針,指向其函數。
在ECMAScript5中規范化了另外一個函數對象屬性:caller,這個屬性保存着調用當前函數的引用,全局變量中對應着null
其獲取方式為arguments.callee.caller(在嚴格模式先訪問arguments.callee要報錯)
我們先貼一張圖出來看看:
各位看到了,我們只是將param作為參數傳了進去,然后在里面給他多加了一個屬性,但是param也多了一個屬性哦!
--------------華麗的分割線------------------
PS:我突然想起了那天面試我錯了一道非常惡心的題,突然想起的,勿噴,實在太惡心了。。。
1 var a = {}; 2 a.a = 6; 3 alert(a.a); 4 5 var b = a; 6 b.a = 66; 7 alert(a.a);
這個我還答對了,但是好像后面類似這樣的題我答錯了,囧:
1 var a = 3; 2 alert(a); 3 a = 4;
就是類似於這樣的題了,我當時是餓了還是在大神面前智商降低了呢?我剛剛突然想起了,覺得好戳哦。。。
--------------華麗的分割線------------------
回到本題,我們來理一理這個東西,我們這里傳遞了一個對象作為函數的參數,與其說是對象,不如說是對象的引用。
ECMAScript所有參數傳遞的都是值,不能通過引用傳遞參數
所以內部改變了那個值也會改變外面的東東,但是傳遞值的話又有所不同:
1 var a = 1; 2 function alertArgurment(d) { 3 d = 2; 4 alert(d); 5 } 6 alertArgurment(a);
這塊里面就是2,外面的a仍然是1了。根據前面的研究我們再修改下程序:
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(d) { 3 d.id = '刀狂劍痴'; 4 arguments[0].qq = '素還真'; 5 for (var k in d) { 6 alert(k + ': ' + d[k]); 7 } 8 } 9 alertArgurment(param); 10 var s = '';
我們既然不能傳遞引用,那么他就直接將對象傳進去了。。。
1 var param = { name: '葉小釵', age: 33 }; 2 function alertArgurment(d) { 3 var tmp = param; 4 d.id = '刀狂劍痴'; 5 arguments[0].qq = '素還真'; 6 var sss = ''; 7 } 8 alertArgurment(param);
大家請設置斷點觀察tmp的變化,d變化了tmp會與之同步,所以我們這里應該是把param直接給傳遞進去了吧:
整理
ECMAScript中所有函數的參數都是按值傳遞。在這點上我們容易模糊,因為引用類型傳遞的時候會完全的復制進去
在傳遞引入引用類型時,會把這個值在內存中的地址復制給一個局部變量,這個局部變量的變化會反應到外部。
就如我們上面的例子:
① 我們創建了一個對象param
② 我們將之轉到函數內部后就復制給了d對象(arguments[0]),d與param現在是同一對象,他們在堆中只有一個對象。
結語
好了,我們隊參數的研究暫時到這里,若您有何疑問請提出