天天看點

JavaScript 函數

javascript 使用關鍵字 function 定義函數

函數可以通過聲明定義,也可以是一個表達式

函數聲明的文法 :

函數聲明後不會立即執行,會在我們需要的時候調用到

分号是用來分隔可執行javascript語句,由于函數聲明不是一個可執行語句是以不以分号結束

javascript 函數可以通過一個表達式定義

函數表達式可以存儲在變量中:

在函數表達式存儲在變量後,變量也可作為一個函數使用:

兩者的差別:解析器會先讀取函數聲明,并使其在執行任何代碼之前可以通路;而函數表達式則必須等到解析器執行到它所在的代碼行才會真正被解釋執行。

以上函數實際上是一個 匿名函數 (函數沒有名稱)。函數存儲在變量中,不需要函數名稱,通常通過變量名來調用。上述函數以分号結尾,因為它是一個執行語句。

1 常見寫法:

2 匿名函數:

3 自調用函數:

4 函數嵌套:

5 函數繼承和構造函數

在以上執行個體中,我們了解到函數通過關鍵字 function 定義。函數同樣可以通過内置的 javascript 函數構造器(function())定義

實際上,你不必使用構造函數。上面執行個體可以寫成:

在 javascript 中,很多時候,你需要避免使用 new 關鍵字

提升(hoisting)是 javascript 預設将目前作用域提升到前面去的的行為。

提升(hoisting)應用在變量的聲明與函數的聲明,是以,函數可以在聲明之前調用:

使用表達式定義函數時無法提升

以上代碼運作即會報錯,原因在于函數位于一個初始化語句中,而不是一個函數聲明。換句話講,在執行到函數所在的語句之前,變量myfunction中不會儲存有對函數的引用;而且,由于第一行代碼就會導緻“unexpected identifier”(意外辨別符)錯誤,實際上也不會執行到下一行。

除了聲明時候可以通過變量通路函數這一點差別之外,函數聲明與函數表達式的文法其實是等價的。

函數表達式可以 "自調用"。自調用表達式會自動調用。如果表達式後面緊跟 () ,則會自動調用。不能自調用聲明的函數。通過添加括号,來說明它是一個函數表達式:

以上函數實際上是一個 匿名自我調用的函數

自調用函數可用來傳參帶傳回值

自執行函數嚴格來說也叫函數表達式,它主要用于建立一個新的作用域,在此作用域内聲明的變量,不會和其它作用域内的變量沖突或混淆,大多是以匿名函數方式存在,且立即自動執行。

在 javascript 中使用 typeof 操作符判斷函數類型将傳回 "function" ,但javascript 函數描述為一個對象更加準确。

javascript 函數有屬性和方法。

arguments.length 屬性傳回函數調用過程接收到的參數個數:

tostring() 方法将函數作為一個字元串傳回:

函數定義作為對象的屬性,稱之為對象方法。

函數如果用于建立新的對象,稱之為對象的構造函數

javascript 函數對參數的值(arguments)沒有進行任何的檢查

函數顯式參數在函數定義時列出

函數隐藏參數(arguments)在函數調用時傳遞給函數真正的值

javascript 函數定義時參數沒有指定資料類型,對隐藏參數(arguments)沒有進行檢測,對隐藏參數(arguments)的個數沒有進行檢測

如果函數在調用時缺少參數,參數會預設設定為: undefined

有時這是可以接受的,但是建議最好為參數設定一個預設值:

或者,更簡單的方式:

如果y已經定義, y || 傳回y, 因為y是 true, 否則傳回 0, 因為undefined為 false

如果函數調用時設定了過多的參數,參數将無法被引用,因為無法找到對應的參數名。 隻能使用 arguments 對象來調用

javascript 函數有個内置的對象 arguments 對象。arguments 對象包含了函數調用的參數數組。通過這種方式你可以很友善的找到每個參數的值:

或者建立一個函數用來統計所有數值的和:

在函數中調用的參數是函數的參數。

如果函數修改參數的值,将不會修改參數的初始值(在函數外定義)。

在javascript中可以引用對象的值,是以我們在函數内部修改對象的屬性就會修改其初始的值。

修改對象屬性可作用于函數外部(全局變量)。

javascript 函數有 4 種調用方式。每種方式的不同方式在于 this 的初始化

一般而言,在javascript中,this指向函數執行時的目前對象

注意 this 是保留關鍵字,你不能修改 this 的值

函數中的代碼在函數被調用後執行

以上函數不屬于任何對象。但是在 javascript 中它始終是預設的全局對象。

在 html 中預設的全局對象是 html 頁面本身,是以函數是屬于 html 頁面。

在浏覽器中的頁面對象是浏覽器視窗(window 對象)。以上函數會自動變為 window 對象的函數

myfunction() 和 window.myfunction() 是一樣的:

這是調用 javascript 函數常用的方法, 但不是良好的程式設計習慣。全局變量,方法或函數容易造成命名沖突的bug

當函數沒有被自身的對象調用時, this 的值就會變成全局對象。

在 web 浏覽器中全局對象是浏覽器視窗(window 對象)。

該執行個體傳回 this 的值是 window 對象:

函數作為全局對象調用,會使 this 的值成為全局對象。使用 window 對象作為一個變量容易造成程式崩潰

在 javascript 中你可以将函數定義為對象的方法。

以下執行個體建立了一個對象 (myobject), 對象有兩個屬性 (firstname 和 lastname), 及一個方法 (fullname):

fullname 方法是一個函數。函數屬于對象。 myobject 是函數的所有者。

this對象,擁有 javascript 代碼。執行個體中 this 的值為 myobject 對象。

測試以下!修改 fullname 方法并傳回 this 值:

函數作為對象方法調用,會使得 this 的值成為對象myobject本身

如果函數調用前使用了 new 關鍵字, 則是調用了構造函數。這看起來就像建立了新的函數,但實際上 javascript 函數是重新建立的對象:

構造函數的調用會建立一個新的對象。新對象會繼承構造函數的屬性和方法

構造函數中 this 關鍵字沒有任何的值。this 的值在函數調用時執行個體化對象(new object)時建立。

在 javascript 中, 函數是對象。javascript 函數有它的屬性和方法。call() 和 apply() 是預定義的函數方法。 兩個方法可用于調用函數,兩個方法的第一個參數必須是對象本身。

兩個方法都使用了對象本身作為第一個參數。 兩者的差別在于第二個參數: apply傳入的是一個參數數組,也就是将多個參數組合成為一個數組傳入,而call則作為call的參數傳入(從第二個參數開始)。call和apply的第一個參數就是this指針要指向的對象

在 javascript 嚴格模式(strict mode)下, 在調用函數時第一個參數會成為 this 的值, 即使該參數不是一個對象。

在 javascript 非嚴格模式(non-strict mode)下, 如果第一個參數的值是 null 或 undefined, 它将使用全局對象替代。

通過 call() 或 apply() 方法你可以設定 this 的值, 且作為已存在對象的新方法調用

javascript 變量可以是局部變量或全局變量

私有變量可以用到閉包

函數可以通路函數内部定義的變量

函數也可以通路函數外部定義的變量

後面一個執行個體中, a 是一個全局變量。在web頁面中全局變量屬于 window 對象。全局變量可應用于頁面上的所有腳本。

在第一個執行個體中, a是一個局部變量。局部變量隻能用于定義它函數内部。對于其他的函數或腳本代碼是不可用的。全局和局部變量即便名稱相同,它們也是兩個不同的變量。修改其中一個,不會影響另一個的值。

變量聲明是如果不使用 var 關鍵字,那麼它就是一個全局變量,即便它在函數内定義

全局變量的作用域是全局性的,即在整個javascript程式中,全局變量處處都在。而在函數内部聲明的變量,隻在函數内部起作用。這些變量是局部變量,作用域是局部性的;函數的參數也是局部性的,隻在函數内部起作用。

設想下如果你想統計一些數值,且該計數器在所有函數中都是可用的。你可以使用全局變量,函數設定計數器遞增:

計數器數值在執行 add() 函數時發生變化。但問題來了,頁面上的任何腳本都能改變計數器,即便沒有調用 add() 函數。如果我在函數内聲明計數器,如果沒有調用函數将無法修改計數器的值:

以上代碼将無法正确輸出,每次我調用 add() 函數,計數器都會設定為 1。javascript 内嵌函數可以解決該問題

所有函數都能通路全局變量。 實際上,在 javascript 中,所有函數都能通路它們上一層的作用域。javascript 支援嵌套函數。嵌套函數可以通路上一層的函數變量。

該執行個體中,内嵌函數 plus() 可以通路父函數的 counter 變量:

如果我們能在外部通路 plus() 函數,這樣就能解決計數器的困境。我們同樣需要確定 counter = 0 隻執行一次。我們需要閉包。

變量 add 指定了函數自我調用的傳回字值。自我調用函數隻執行一次。設定計數器為 0。并傳回函數表達式。add變量可以作為一個函數使用。非常棒的部分是它可以通路函數上一層作用域的計數器。這個叫作 javascript 閉包。它使得函數擁有私有變量變成可能。計數器受匿名函數的作用域保護,隻能通過 add 方法修改。

閉包是可通路上一層函數作用域裡變量的函數,即便上一層函數已經關閉

繼續閱讀