Javascript面向對象編程指南筆記-第三章-函數

Javascript面向對象編程指南筆記-第三章-函數。


3-1 什麼是函數

所謂函數,本質上就是一種代碼的分組形式。
我們將一組代碼賦予名字,便於日後調用。

通常來說,函數聲明 通常由一下幾個部分組成:

function 子句 函數名稱 函數所需參數,通常有0到多個參數,參數之間用逗號分割。 函數所執行代碼塊,稱之為函數體。 return 子句。如果沒有顯式的返回值,我們就默認為返回值是undefined

需要註意的是,一個函數隻有一個返回值,如果需要返回多個值,可以考慮放進一個數組中,以數組元素的形式返回。


3-1-1 調用函數

如果要使用一個函數,就必須要調用它。
調用方式:函數名+(參數)。

>>> var result = sum(1,2);
>>> result;
>>> 3
//調用sun()函數,返回值賦予result.

3-1-2 參數

通常定義函數時,我們會設置函數所需參數,當然如果不設置,或者調用時忘記傳遞數值,Javascript就會自動將其設定為undefined

>>> sum(1);
NaN
// 因為隻設置瞭一個參數,所以函數將 1 與 undefined 相加。

對於所以傳遞來的參數,JS來者不拒。
所以即使參數傳遞過多,多餘部分會被忽略掉

其實,我們可以創建一些在參數數量方面更為靈活的函數。 這得益於每個函數內部都有一個內建的 arguments 數組, 它能返回函數所接收的所有參數

>>> function args() { return arguments; }
>>> args();
[]
>>> args(1, 2, 3, 4, "haha");
[1, 2, 3, 4, "haha"]

通過 arguments 數組,我們能進一步完善sum()函數功能, 使之能對任意數量的參數執行求和運算。

function sumOnSteroids() {
    var i, res = 0;
    var number_of_params = arguments.length;
    for (i = 0; i < number_of_params; i++) {
        res += arguments[i];
    }
    return res;
}
// arguments.length 返回的事函數所調用時所接收的參數數量。
// (其實arguments不是一個數組,而是一個類似數組的對象,第四章會解答)

3-2 預定義函數

Javascript 引擎中有一組可以供隨時調用的內建函數。

parseInt ( ) parseFloat ( ) isNaN ( ) isFinite ( ) encodeURI ( ) decodeURI ( ) encodeURICompoent ( ) decodeURICompoent ( ) eval ( )


 

3-2-1 parseInt( )

parseInt()會試圖將其收到的任何輸入值(通常是字符串)轉換成整數類型輸出。如果轉換失敗就返回NaN。

>>> parseInt('064');
064
>>> parseInt('abc123');
Nan
>>> parseInt('1abc123')//註意第一位是數字
1
>>> parseInt('123abc')
123

除此之外,該函數還有個可選的第二參數:radix, 它負責設定函數所期望的數字類型-十進制,二進制,八進制,十六進制等。如果我們以十進制輸出FF,結果為NaN,如改為十六進制,結果為255。

>>> parseInt('FF', 10);
NaN
>>> parseInt('FF', 16);
255

通常如不設置第二參數,函數默認為十進制。
但如果首參字符串為0x開頭,第二參數默認為十六進制。
如果0開頭,默認為八進制。


 

3-2-2 parseFloat( )

功能和parseInt( )基本相同,不過隻支持轉換為十進制
與parseInt( )相同,在遇到第一個異常字符時會放棄
與parseInt( )不同的是,parseFloat( )可以接收指數形式的數據。

>>> parseFloat('123e-2');
1.23

 

3-2-3 isNaN( )

可以通過此函數確定某個輸入值是否是可以參與算術運算的數字。
因此可以來測試parseInt()和parseFloat()的調用成功與否。

>>> isNaN(NaN)
true
>>> isNaN(123)
false
>>> isNaN(1.23)
false
>>> isNaN(parseInt('abc123'))
true

註:NaN === NaN 返回值是false


 

3-2-4 isFinite( )

檢查輸入是否為既非 infinity 也非 NaN 的數字


 

3-2-5 URL的編碼與反編碼

在URL(Uniform Resource Locator)或 URI 中有一些字符具有特殊含義,因此我們需要轉義.
* encodeURI():返回一個可用的URL 解碼:decodeURI()
* encodeURIComponent(): 認為我們所傳遞的僅僅是URL的一部分。解碼:decodeURIComponent()


3-2-6 eval( )

會將輸入字符串當做Javascript代碼來執行。

>>> eval('var ii = 2;');
>>> ii;
2

避免使用 避免使用 避免使用


3-2-7 alert( )函數

不是JS核心一部分,不在ECMA標準中,由瀏覽器提供,顯示文本消息對話框。

但是這個函數會阻塞當前瀏覽器進程,也就是說代碼會停止執行

3-3 變量的作用域

在JS中,不能為變量定義特定的作用域。
但是可以定義函數域。
如果變量是在某個函數中定義的,那麼函數以外不可見。
但如果在 if 或 for 中定義,在代碼塊外可見

全局變量 定義在所有函數之外
局部變量 定義在函數中

如果聲明變量時沒有用 var 語句,變量默認為全局變量


3-4 函數也是數據

其實函數也是一種 數據類型

function f(){return 1;}
var f = function(){return 1;}//函數標識記法 function literal notation

對函數變量調用 typeof ,返回字符串為 function

JS中, 函數是一種數據,隻不過這種數據有兩個重要特性:

它們包含是代碼 它們是可執行的

因為函數也賦予變量數據,所以函數命名規則與一般變量相同 —— 即函數名不能以數字開頭, 可以由任意的字母,數字和下劃線組合。

3-4-1 匿名函數

沒有被賦予任何變量的數據叫做 匿名數據

沒有名字的函數叫做 匿名函數

>>> function(a){return a;}

我們可以將匿名數據片段設置為函數,這樣就有瞭兩種優雅的用法:

我們可以將匿名函數作為參數傳遞給其他函數 ,這樣,接收方函數就能利用我們所傳遞的函數來完成某些事情。 我們可以定義某個匿名函數來執行某些一次性任務。

下面為實例:

3-4-2 回調函數

既然函數可以像其他數據那樣賦值給某個個變量,可以被定義,刪除,拷貝,那麼也可以當場參數傳遞給其他函數。

下面我們定義一個以兩個函數為參數的函數。

function invoke_and_add(a,b){
    return a() + b();
}
function one(){
    return 1;
}
function two(){
    return 2;
}
>>> invoke_and_add(one,two);
3

事實上我們可以用匿名函數來代替 one() 和 two()。

invoke_and_add(function(){return 1;}, function(){return 2;})

3-4-3 回調函數

在編程過程中,我們通常需要將一個函數的返回值傳遞給另一個函數。

function multiplyByTwo(a, b, c) {
    var i, ar = [];
    for(i = 0; i < 3; i++) {
        ar[i] = arguments[i] * 2;
    }
    return ar;
}
function addOne(a) {
    return a + 1;
}

>>> multiplyByTwo(1, 2, 3);
[2, 4, 6]
>>> addOne(100);
101

下面我們定義一個用於儲存元素數組,實現三個元素在兩個函數之間傳遞。

var myarr = [];
myarr = multiplyByTwo(10, 20, 30);
[20, 40, 60]

然後,用循環遍歷每個元素, 並將它們分別傳遞給 addOne()。

>>> for (var i = 0; i < 3; i++){myarr[i] = addOne(myarr[i]);}
>>> myarr
[21, 41, 61]

在這裡我們還是使用瞭兩個循環。
我們需要對multiplyByTwo()函數做一些改動, 使其接受一個回調函數。

function multiplyByTwo(a, b, c, callback){
    var i, ar = [];
    for(i = 0; i < 3; i++){
        ar[i] = callback(arguments[i] * 2);
    }
    return ar;
}

現在我們隻需要調用一次函數。

>>> myarr = multiplyByTwo(1, 2, 3, addOne);
[3, 5, 7]

我們還可以用匿名函數代替addOne(), 這樣可以節省一個額外的全局變量。

>>> myarr = multiplyByTwo(1, 2, 3, function(a){return a + 1});
[3, 5, 7]

3-4-4 自調函數

(
    function(){
        alert('');
    }
)()
// 這種匿名函數可以在定以後自行調用
(
    function(name){
        alert('Hello ' + name + '!');
    }
)('dude') //立即調用

自調函數不會產生任何全局變量,但是是無法重復執行。
更加適合一次性的或初始化的任務。


3-4-5 內部(私有)函數

我們可以在函數內部定義另一個函數

function a(param){
   function b(theinput){
       return theinput * 2;
   };
   return 'The result is ' + b(param);
};
var a = function(param){
   var b = function(theinput){
       return theinput * 2;
   };
   return 'The result is ' + b(param);
};//函數標識記法

當調用全局函數a()時,本地函數b()會在內部調用,由於是本地函數,在外部是不可見的,所以也叫私有函數。

好處:

有助於我們確保全局名字空間的純凈性(命名沖突小) 私有性——隻講必要函數暴露給“外部世界”


3-4-6 返回函數的函數

函數都會有一個返回值,及時不是顯式返回,也會隱式返回一個 undefined,我們也可以返回一個函數。

function a() {
    alert('A!');
    return function(){
        alert('B!');
    };
}

如果想讓返回的函數立刻執行,可以在後面加上一堆括號。

>>> a()();

3-4-7 能重寫自己的函數

由於一個函數可以返回另一個函數, 因此我們可以用新的函數來覆蓋舊的。

>>> a = a();//用a()的返回值來重寫自己。

我們其實也可以在函數內部重寫函數自身

function a() {
    alert('A!');
    a = function(){
        alert('B!');
    };
}

第一次調用執行 alert(“A!”)
第二次執行alert(“B!”)

發佈留言