JavaScript物件導向程式設計(4): 函數

來源:互聯網
上載者:User
在很多語言中,函數(Java裡面成為方法)和對象時截然不同的兩種東西。函數被定義為對象的動作,或者是全域的(像在C++中的main函數一樣)。但是在JavaScript中,函數和對象的界限卻顯得不那麼明顯。  1. 函數的定義 JavaScript中有很多種定義函數的方法: function hello() { alert("Hello!"); }        
var hello1 = function() { alert("Hello!"); };        
var hello2 = new Function("", "alert('Hello!');");        
hello();        
hello1();        
hello2(); 上面給出了三種JavaScript的函數定義語句。第一句是常見的定義,看上去和Java等語言沒有太大的不同。這句是定義了一個具名函數,按照上面的例子,這裡的函數定義名字為hello。第二句是將一個匿名函數定義好後賦值給一個變數,於是通過這個變數就可以引用這個匿名函數。這兩句看上去效果差不多,但是它們是不一樣的:第一句定義的是一個具名函數,第二句定義的是一個匿名函數——儘管你可以通過這個變數引用到這個匿名函數,但實際上它還是匿名的。它們的區別可以由下面的看出:
hello(); 
hello1(); // error
function hello() { alert("Hello!"); }
var hello1 = function() { alert("Hello!"); };

具名函數的作用範圍是全域的:你可以在定義之前使用這個函數。但是匿名函數的定義是後向的,像C/C++一樣,必須在定義之後才能使用。這就是為什麼hello可以使用,但是hello1就會有錯誤。然後試想一下這是為什麼呢?JavaScript的解釋過程和HTML一樣是從上到下的。所以,這裡的匿名函數就相當於是一個變數的定義,因此在JavaScript解譯器解釋執行時並不知道這個變數的定義,因此發生錯誤。但是,對於函數的定義則是掃描全域。

 第三個語句就很有意思了。它建立了一個Function類的對象。這個建構函式(姑且這麼叫吧)具有兩個參數,第一個是函數的參數,第二個是函數體。具體來說,下面的兩個函數定義是等價的:function sayHelloTo(name) {
        alert("Hello, " + name);
}
var sayHelloTo1 = new Function("name", "alert('Hello, ' + name)"); 這種使用Function進行定義的方式並不常見,但是這個語句顯示的特性卻很有趣:它意味著,你可以使用這種建構函式在運行時動態建構函式!這是一般的語言沒有的特性。  2. 函數的參數 JavaScript的函數也是相當的靈活,不僅是它的定義方式多種多樣,甚至它的參數都有“奇怪”的行為。由於JavaScript是弱類型的語言,因此,它不能對你的函數參數類型做檢測,甚至不能保證你傳入的參數個數是否和函數定義一致。這就需要有一些特殊的檢測。
function sum2(a, b) { 
        alert(a + b);
}
sum2(1); // NaN
sum2(1, 2); // 3
sum2(1, 3, 5); // 4
看這個例子,僅僅接受兩個參數的函數,在調用時可以有任意個參數!但是,它僅取用合格個數,在這裡也就是前兩個參數。所以,當你傳入一個參數時,JavaScript試圖將兩個數字加起來,結果第二個參數不存在,因此傳回值是NaN。第三種情況,實參個數多於形參個數,此時JavaScript只取前兩個參數相加。 儘管很不正式,但是可以說,JavaScript的函數參數是不定參數,也就是說,你可以傳入任意的參數值。使用JavaScript函數內建的arguments就可以遍曆所有傳入的參數。比如下面的代碼:
function sum() { 
        var total = 0;
        for(var i = 0; i < arguments.length; i++) {
                total += arguments[i];
        }
        alert(total);
}
sum(1, 2);
sum(1, 2, 3);
arguments的行為很像數組,但它並不是數組。可以使用typeof操作符看一下,也可以調用它的constructor屬性。 這裡有一點需要說明,arguments有個callee屬性,可以調用arguments自身所在的函數。也就是說,可以通過這個屬性遞迴調用函數自身。所以,即使是匿名函數,也可以實現遞迴調用。如:
function sum(n) { 
        if(n <= 1) {
                return 1;
        }
        return n + arguments.callee(n - 1); // 遞迴調用自身
}
alert(sum(100));
我覺得大家都會知道這個著名問題的答案的。  3. 函數也是對象 回想一下上面的第三個語句,它已經強烈暗示了,函數其實也是對象!那麼,作為一個對象,函數應該具有對象的一切特性:添加屬性、刪除屬性、作為傳回值等等。是的!JavaScript的函數就是這麼樣的!
function hello() { 
        alert("Hello!");
}
hello.name = "Tom"; // 添加屬性
alert(hello["name"]);
delete hello.name; // 刪除屬性
alert(hello.name);
// 賦值給變數
var hello1 = function() { alert("hello1"); };
hello1();
// 作為數組元素
function show(x) { alert(x); }
var arr = [show];
arr[0](5);
// 作為函數的參數
function callFunc(func) {
        func();
}
callFunc(function() {
        alert("Inner Function.");
});
// 作為函數的傳回值
function show() {
        return function(n) {
                alert("number is " + n);
        };
}
show()(10);
瞧!凡是對象可以做到的,函數統統都能做到!JavaScript中的函數就是對象! 現在我們已經從數組,逐漸開始到對象和函數。這些都是基本概念,後面,我們將對JavaScript的物件導向特性做進一步的介紹
相關文章

聯繫我們

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