javascript筆記:javascript裡面不同function定義的區別

來源:互聯網
上載者:User

今天看到javascript的一條經驗的總結,總結如下:

在Javascript中定義一個函數,有兩種寫法:

第一種是:function ftn(){}

另外一種是:var ftn = function(){}.

筆者說這兩種寫法是完全等價的。但是在解析前,前一種寫法會被解析器自動提升到代碼的頭部,因此違背了函數先定義後使用的原則,所以建議定義函數時候,全部採用後一種寫法。

看完這句話,我第一個感覺是兩個在使用時候是完全一致的,只是解析上有所差異。但是他的解釋“前一種寫法會被解析器自動提升到代碼的頭部”讓我很困惑。

如是我有了下面第一個測試:

 1    function ftn()
2 {
3 alert('old');
4 }
5
6 var b = ftn;
7
8 function ftn()
9 {
10 b();
11 alert('new');
12 }
13
14 ftn();//瀏覽器報記憶體溢出

  接下來我做了第二個測試:

 1 var ftn = function()
2 {
3 alert('old');
4 }
5
6 var b = ftn;
7
8 var ftn = function()
9 {
10 b();
11 alert('new');
12 }
13
14 ftn();//old,new依次彈出

網上的對這個解釋是:第一種方式,剛開始其實沒有重新定義ftn這個Function而在裡面執行了其本身。第二種方式,ftn=function()這裡沒有執行到Function裡面的代碼ftn已經被重新定義了,所以這裡的重定義是有效。

但是這種解釋讓我感覺還是雲裡霧裡,那麼我再做了一個下面的測試:

 1 function ftn()
2 {
3 alert('old');
4 }
5
6 var b = ftn;
7
8 function ftn()
9 {
10 b();
11 alert('new');
12 }
13
14 alert(b);//結果是重新定義的ftn內容

測試結果發現,重新定義ftn後,b的內容也會隨著改變。

下面我又做了兩外一個測試:

 1 var ftn = function()
2 {
3 alert('old');
4 }
5
6 var b = ftn;
7
8 var ftn = function()
9 {
10 b();
11 alert('new');
12 }
13
14 alert(b);//結果是老的ftn內容

這樣就很有意思了,在javascript裡面除了基礎資料型別 (Elementary Data Type),其他類型都是對象,對象是存在堆裡面,它的別名是存在棧裡面的地址,後一種測試很明顯可以用這樣的原理來理解。那麼前面的測試為什麼b會隨著ftn的重新定義而改變了?

我有一種新解釋,不知道對不對,在所有的講javascript書裡都會提到,javascript裡面是沒有方法重載的,後面定義的重名function會覆蓋前面的function,var b = ftn;這句話是把b和ftn的引用指向同一個堆裡面的記憶體,而重新定義function ftn(){}後,新的function對象覆蓋了老的對象,而b和ftn引用的堆地址空間沒變,如果真是這樣,那麼這種寫法就合理了:

 1 function ftn()
2 {
3 alert('old');
4 }
5
6 var b = ftn;
7
8 var ftn = function()
9 {
10 b();
11 alert('new');
12 }
13
14 alert(b);//老的ftn
15 alert(ftn);//新的ftn
16 ftn();//old ,new

 這樣新的ftn在棧裡面的地址改變了,指向了新的function對象的定義,而原來的function沒有被覆蓋,還儲存,所以b還是老的ftn引用的地址。

 剛剛寫了一篇對javascript裡面function理解的文章,回頭再思考下我這邊文章的內容,覺得自己通過測試的結果的理解還是有點問題,其實理解還是要從編譯,啟動並執行原理進行思考。javascript都是在執行代碼時候才編譯代碼,因此我們var定義的類型可以不定,我們封裝的對象還時候添加屬性和方法,因此可以這麼理解我標題所帶來的問題,javascript一般的語言,例如定義一個變數var obj = new Object()只是做了一個很初的處理,在javascript裡面叫做先行編譯,這種先行編譯的能力很弱,弱到你可以隨便更改,而不會影響程式的運行,當對象被調用時候,javascript解譯器才會進行編譯,然後運行代碼,這和java很不一樣,java是先把代碼編譯好,調用他的時候才運行,這就是指令碼語言的特點,所以指令碼語言大多不快。但是當你這麼定義函數:fonction ftn(){},這種就把代碼進行了編譯,也就是執行過了,這種寫法和java函數的定義很相似了。這是我的新解,我覺得這個解釋更加合理些。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.