1. 程式人生 > >JavaScript中的函式

JavaScript中的函式

JS中的函式給我的感覺還是蠻新奇的,以前只學過C和Java,都是不可以函式巢狀的強型別語言,(儘管JDK10以後,Java引入了局部型別推斷(Local-Variable Type Inference),即我們平時說的var),弱型別語言的一些特性,我還是需要些時間慢慢去適應

目錄

      函式宣告

      函式表示式

一.  弱型別語言無法輸出地址

弱型別語言的方法雖然可以輸出,但是得到的並不是期望的地址值,而是整個函式體,儘管JS也有堆和棧的概念,但是地址不會被輸出

<script>
    function testMethod() {
        alert("我真帥");  
    }

    testMethod();
    console.log(testMethod);      // 控制檯中輸出 內容同下
    document.write(testMethod);   // function testMethod() { alert("我真帥"); }
</script>

  輸出到瀏覽器螢幕上的是 function testMethod() { alert("我真帥"); },而在控制檯中輸出則更規範,保留了程式碼格式,一般都在控制檯中輸出

二. 3種函式定義方式

    3種定義方式,可以總的被歸納為兩種,如下所示

  • 函式宣告

  • 函式表示式

    其中,函式表示式還可以再進一步細分為命名函式表示式匿名函式表示式

(1)函式宣告

<script>
   function test() {
        console.log("函式宣告");
   }
   // test();
</script>

  如上所示,一個函式便被聲明瞭,但是不會執行,因為此時沒有JS程式碼呼叫它,此時只需要把註釋放開,便可在控制檯看到輸出

 (2.1)命名函式表示式

<script>
   var named = function abc () {
        console.log("命名函式表示式");
   }
   named();
</script>
 命名函式表示式的命名二字,表現在function後面的“abc”那,但是實際上若想呼叫這個函式還是需要named();這樣呼叫,後面的“abc”基本上是沒有任何意義的,。因此實際開發一般都是使用匿名函式表示式

(2.2)匿名函式表示式

<script>
     var unnamed = function () {
         console.log("匿名函式表示式");
     }
     unnamed();
</script>

  匿名函式表示式結構更加清晰,刪除了無用的命名

  那麼,儘管命名函式表示式沒用,那麼它們的區別在哪裡呢?

  答案其實就是命名那

<script>
        // (1)函式宣告
        function test() {
            console.log("函式宣告");
        }
        // (2)函式表示式
        // (2).1 命名函式表示式
        var named = function abc () {
            console.log("命名函式表示式");
        }
        // (2).2 匿名函式表示式
        var unnamed = function () {
            console.log("匿名函式表示式");
        }
        // (2).1和(2).2的區別在於各自的name屬性 2.1為abc 2.2為unnamed 此外,以函式宣告方式定義函式同樣有name 即它本身
        console.log("test.name = " + test.name);            // test
        console.log("named.name = " + named.name);          // abc  唯一一點不同之處 開發一般都用匿名
        console.log("unnamed.name = " + unnamed.name);      // unnamed
</Script>

  如上程式碼

  可以看到,無論是函式宣告還是匿名函式表示式,方法的name屬性值都是各自的方法名,唯獨命名函式表示式是function後面跟著的變數名“abc”,區別僅在於此

三.  形參和實參列表

 JavaScript中的形參因為弱型別語言的緣故,不再需要定義變數資料型別,直接寫名字即可,且不限制傳遞引數個數(類似於Java的JDK5引入的可變引數,不過功能更加強大),但這樣的同時也會引發一些問題,比如傳遞的引數個數和定義的形參個數不同,此時需要以arguments物件取出實參。 具體看下面的程式碼

<script>
    function js (a,b) {
        // 形參相當於 var a,b;
        if (js.length > arguments.length) {
            console.log("形參多了");
        } else if (js.length < arguments.length) {
            console.log("實參多了");
        } else {
            console.log("相等");
        }
        for (var i = 0;i<arguments.length;i++){
            alert(arguments[i]);
        }

        js(1,2,3,undefined,null,NaN);
</script>

   形參定義了兩個,但實際傳遞的引數有5個,此時如果想使用其餘被傳遞的引數,則需要使用arguments物件獲取,注意,arguments是物件而不是陣列,arguments[0]只是其一個屬性,而這個屬性是傳遞的實參的副本

除此之外,形參還和arguments物件的屬性存在對映關係,若修改了形參值會通過對映改變arguments物件屬性的值(但二者實際上並非指向同一塊記憶體),即形參值,但是也存在一定的約束關係,形參值只能修改和實參值共有的部分,如下所示

<script>
    function testArgs(a,b,c,d) {
        // 相當於 var a,b,c,d;
        a = 11;
        b = 22;
        c = 33;
        d = 44;
        console.log("arguments[0] = " + arguments[0]); // 11
        console.log("arguments[1] = " + arguments[1]); // 22
        console.log("arguments[2] = " + arguments[2]); // 33
        console.log("arguments[3] = " + arguments[3]); // undefined
        //由此可見 這種對映關係只存在於實參和形參的共有部分
    }

    testArgs(1,2,3);

</script>

  實際被傳遞的引數只有3個,但此時形參定義了4個,那麼arguments陣列的屬性也只有arguments[0],arguments[1],arguments[2],此時檢視arguments[3]自然是undefined