javascript應該注意的小case–函數

來源:互聯網
上載者:User

函數function在js是非常重要的存在,我們平常所討論的js的”物件導向”,都是在它的基礎上的,可以說我們應該相當的瞭解,它存了太多獨特的地方了。

 

每個函數都是function類型的執行個體

首先讓我們來理解這句話:每個函數其實是function類型的執行個體。也就是說我們聲明的函數都是對象,有自己的屬性和方法,函數名不過是指向該對象的一個指標

看下面這個例子:

  function myfuc(arg) {        alert(arg);    }    var anfuc = myfuc;    myfuc = null;    anfuc(1);  //  報錯,還是彈出1??

 

結果是彈出1,myfuc不過是指向我們函數對象的一個指標,它指向null之後,並不影響anfuc的,因此調用無影響。

 

函數的內部屬性

arguments和this:arguments是一個類數組對象,它包含調用函數時傳入的所有參數,你在函數裡可以用arguments[0]、arguments[1]…來訪問傳入參數;此外,它還有一個屬性callee,它也也是一個指標,指向擁有這個arguments對象的函數,這個屬性在我們遞迴中相當有用,比直接的函數名易維護且健壯。

   function myfuc(arg) {        if (arg <= 1) {            return 1;        } else {            return arg + myfuc(arg - 1);        }    }    function anfuc(arg) {        if (arg <= 1) {            return 1;        } else {            return arg + arguments.callee(arg - 1);        }    }

 

這兩個函數雖然寫法上有點不一樣,但是是相同的目的,在這裡強烈推薦採用第二種:在任何時候你想修改該函數名,只需要修改聲明即可,同時看下邊的例子。

    var myfuc2 = myfuc;    var anfuc2 = anfuc;    myfuc = null; anfuc = null;    alert(anfuc2(3));  //  彈出6    alert(myfuc2(3));  // 沒彈出,並報錯

 

myfuc2的調用中,遞迴時還去尋找myfuc調用,但是早已“物是人非”了,而anfuc2裡arguments.callee始終指向當前調用的函數,也就是anfuc2。

 

this屬性,函數執行時,指向其執行所在的範圍,正確的理解它的意義是很重要的。

 

    var name = "window";    function sayName() {        alert(this.name);    }    var o = new Object();    o.name = "object";    o.sayName = sayName;    sayName();  //  彈出window    o.sayName();  //彈出 object

 

儘管sayName和o.sayName指向同個對象,但是他們的調用確輸出了不一樣的結果。我們知道,我們聲明的全域變數和函數是屬於window的,其實相當於window.name,window.sayName,而這個this動態指向了擁有該方法的對象。

 

函數的屬性和方法

剛剛介紹的是在函數休內才能使用的屬性,而既然函數是對象,那麼它肯定有可供我們使用的屬性和方法。

length屬性:函式宣告時希望接受到參數的個數。

prototype屬性:這個。。這個。。這個是js強大所在,它不僅能讓js比較完美的實現“類”、具有一些物件導向語言的一些特性如繼承等,更能擴充內建對象所不具備的功能和屬性。

apply方法和call方法:這兩個方法都是讓函數“自己調用自己”的,只不過傳參方式不一樣而已。

 

沒有重載的重載

js是沒有重載的,試圖重載都會覆蓋有前一個的函式宣告,不過通過js的特性,我們可以實作類別似重載的一些特性。由於函數是對象,聲明不過是指向該對象的指標而已,因些js在定位函數時只會根據函數名,根本不會考慮你傳的參數,因此我們可以用以下兩種方式實作類別似重載,這兩種方式本質是一樣的,只是表現形式上的差別。

1,arguments

   function sayHi() {        var result = "default";        if (arguments[0]) {            result = arguments[0];        }        if (arguments[1]) {            result += arguments[1];        }        if (arguments[2]) {            result += arguments[2];        }        if (arguments[3]) {            result += arguments[3];        }        // 此處你甚至可以遍曆arguments來支援無限的參數        return result;    }    alert(sayHi("a"));  //  a    alert(sayHi("a", "b"));  // ab    alert(sayHi("a","b","c"));  //abc

 

從調用上來看,是不是實現了重載。

2,聲明所有參數

function sayHi(a,b,c/*還可以更多*/) {        var result = "default";        if (a) {            result = a;        }        if (b) {            result += b;        }        if (c) {            result += c;        }        // 如果還有可以支援更多        return result;    }

 

調用是一樣的,結果也是一樣的。

 

第一種方式更靈活,第二種則更易讀,對調用者來說更友好。推薦一般參數不多的話,使用第二種,如果要支援無限參數,只有採用第一種。極度不推薦兩種混用,那會讓代碼結非常亂,維護和以後擴充都會有不少麻煩。

 

函數的建立方式

一般來說我們有兩種方式建立函數:

1,函式宣告方式:function func(){}

2,函數運算式:var func = function(){}

 

這兩種難道就只是表現形式的差別嗎??當然不是,解析器在解析js時,會優先處理函式宣告,會在所有任何需要執行的代碼之前讓函數可用;而函數運算式只有在執行到所有行時,才會被解析執行。

也就是說:

 sayHi();    function sayHi() {        alert("hi");    }

 

這樣的方式,代碼是沒問題的,並且會彈出hi.

但是

sayHi();    var sayHi = function() {        alert("hi");    }

 

這種方式,會報錯,缺少對象。

 

匿名函數和閉包

匿名函數也稱做lambda函數,一般情況下,我們會在以下幾種情況下會用到匿名函數:

1,回呼函數

2,函數做為傳回值

3,外掛程式形式的開發

如我們經常看到的如:

(function(){//  代碼})();(function($){//  代碼})(jQuery);

 

第二個是jquery推薦的外掛程式開發的方式,這裡聲明一個匿名函數,然後立即執行。函數內部聲明變數和函數,除了綁定給全域變數的一些變數和函數,我們在外部是不能訪問,起到隔離性的作用,不會對頁面造成影響,內部沒有閉包的存在,函數執行完畢後,變數函數就會被回收。

 

很多的匿名函數往往能看到閉包的身影,閉包又是什嗎?

看一個例子:

function createFunc(){var name = "123";return function(){alert(name);};}var func = createFunc();func(); //  彈出123

 

這是一個閉包的簡單例子,createFunc返回了一個匿名函數,一般情況下,一個函數執行完畢後,其內部變數就會被回收,但是createFunc返回的函數裡卻保持著對內部變數name的引用,因些我們在外部調用然後執行func,仍然可以使用,只要func存在,我們執行createFunc時所建立的內部變數就會處於記憶體中的一個位置,直到我們顯示的設定func = null,這次createFunc()建立的name才會被回收。

 

閉包就是有權訪問另一個函數範圍變數的函數。它會讓另一個函數內部的變數仍然處理有效狀態,這有時會為我們帶來莫大的方便,但是我們有時可能要考慮閉包的使用:就是因為閉包的存在,函數執行完畢後,其內部所有的變數就不能被立即回收,仍然處於記憶體中。

 

js的函數即獨特又很重要,用其它語言的方式使用js的函數,即不能體現出它的強大,有時還可能陷入困惑。它也使js強大,使得js具備一些封裝、繼承等進階特性,更有利於我們開發健壯、易維護的應用。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.