前言
我最近在思考一個問題,我本身平時還是積累了不少東西,面試時候問的東西基本逃不出寫的部落格(當然,進階階段的就不行了),但是真的被問到時我卻不一定答得上來。
知道且能回答,回答的效果都不是很好。。。。這是一個讓人很囧的事情,另外,按道理說阿里面試是完蛋了,後面再慢慢找工作吧,休息一下也不錯的。
除了記憶力意外,心態也是一個問題,比如我最常說的一句話就是:
恩,你說這個我知道,我還特意學習過,寫了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(在strict 模式先訪問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現在是同一對象,他們在堆中只有一個對象。
結語
好了,我們隊參數的研究暫時到這裡,若您有何疑問請提出