函式
JavaScript 是透過建構式來模擬物件類別,可建立實體。
若函式內已建立物件,並回傳物件,則可直接使用,不需再用 new 建立物件。
建構式最外層一定是函數,但此函數內可有屬性及方法(function)。
parameters: 指的是在函式的那些傳入參數名稱的定義
arguments: 指的是當函式被呼叫時,傳入到函式中真正的那些值。我們在文章中會以"實際傳入參數值"來說明。
函數種類
//1.函式定義 - 使用有名稱的函式
function sum(a, b){
return a+b
}
//2.函式表達式 - 常數指定為匿名函式
//此處的常數就是函數,可被當成參數使用或做為一個變數的值
const sum = function(a, b) {
return a+b
}
//3.建構式(內含 this 關鍵字)
function PhoneTemplate(brand, modal, withCamera) {
this.brand = brand;
this.modal = modal;
this.withCamera = withCamera || false;
this.takePhoto = function () {
if (this.withCamera) {
console.log(this.modal + ' 照相');
} else {
console.log(this.modal + ' 這台沒有照相功能');
}
}
}3.箭頭函式
傳入參數預設值
在ES6中加入了函式傳入參數的預設值指定語法,現在可以直接在傳入參數時就定義這些參數的預設值,這個作法是建議的用法:
在JavaScript中function可當成參數傳入,而且也可以return function。
不固定傳入參數(Variadic)與其餘(rest)參數
作用範圍(scope)
php不同,在外的變數無法帶入function內,除非加上use()。
或本身就是全域變數。例:$_POST, $_GET...
對比使用let來宣告變數,let y位於區塊{}中,無法在外部環境獲取
靜態(Static)成員
所謂靜態是指建構式直接取值或賦值,不必實體化。
不只是函數可用靜態方式來擴充成員。函式在實體化後,也可擴充成員。
提升(Hoisting)
ES6函數中的變數/常數、函式、類別都有提升(Hoisting)的特性。 非順序執行到時才影響函數內的值,與一般程式不同。
CPS風格(確保依序執行,如CALLBACK)
延續傳遞風格(Continuation-passing style, CPS)
JavaScript中會大量使用CPS風格,主因是只有單執行緒。
優點:CPS用的是明確地移轉控制權到下一個函式中,也就是使用"延續函式"的方式
缺點:CPS風格在愈複雜的應用情況時,程式碼愈不易撰寫與組織,維護性與閱讀性也很低
回調(callback)
使用匿名函式的語法,直接寫在函式的傳入參數中。 回調(callback)提供了一種彈性的機制,讓程式開發者可以自行定義在此函式的最後完成時,要如何進行下一步。
異步回調函式(不阻塞主線程式執行)
同步是由上往下依順序執行,一個執行程序完成後才會再接著下一個,一般的程式語言都是按照這樣的流程來執行。但遇到執行的動作需要等候時,就產生阻塞的問題。
異步是為了解決阻塞,而把需等候的動作放入queue中,等候執行。最常使用的例子是用setTimeout這個內建的方法。
Callbacks(回調),常常用來呼叫異步回調函式
異步程序(函式)間沒辦法保証執行的時間順序,但原則是先進先出
事件大多是異步程序。例:在JavaScript中有一個不斷偵測事件發生的事件迴圈(Event Loop),所有在網頁上的DOM元素註冊的事件,都會進入一個佇列(queue)中,等待被觸發事件
所有的同步回調函式都執行完成了,才會開始依順序執行異步的回調函式。
bFunc中使用了計時器setTimeout會把傳入的回調函式進行異步執行,也就是先移到工作佇列中,等執行主執行緒的呼叫堆疊空了,在某個時間回到主執行緒再執行。所以即使它的時間設定為0秒,裡面的回調函式並不是立即執行,而是會暫緩(延時)執行的一種回調函式,一般稱為異步回調函式。
異步回調函式還有另一個名稱是延時回調(defer callback)
閉包 closure
閉包的最大特點(賣點)就是它會記憶函式建立時的環境,取得function建立當下的預設值。
在閉包中所記憶的變數與值,通常稱為自由(free)變數或獨立(independent)變數,這些變數是在函式中使用,但被封入作用域之中。
this非作用鏈域的一員,不會記憶在閉包中
this的分界
解決方式是要利用作用域鏈(Scope Chain)的設計,也就是說,雖然inner函式與外面的outter分屬不同函式,但inner函式具有存取得到outter函式的作用域的能力,所以可以用這樣的解決方法:
this (call , apply , bind)
JavaScript語言中因為在設計上並不是以類別為基礎的物件導向,所以this的指向的是目前呼叫函式或方法的擁有者(owner)物件,也就是說它與函式如何被呼叫或調用有關,雖然是同一函式的呼叫,因為不同的物件呼叫,也有可能是不同的this值。
call(obj) 或 bind(obj) 內的 obj 是 this 指向的物件,不論在 func 或 obj 內的 this 皆指向相同的 obj。也就是 this 的指向改為後方帶入的obj 參數。被戲稱為認賊作父。
call 和 apply
兩者皆可動態改變this的指向,區別在於call()第二個參數後放值,apply第二個參數後放陣列。(第一個參數都放物件,this會改為指向此物件)
bind
也可動態改變this的指向,並且回傳新函數。
傳入的第一個參數為this,之後傳入的參數,會依原參數的順序傳入。
匿名函式與IIFE
匿名函式實現只執行一次的函式,也就是IIFE結構。 IIFE在執行環境一讀取到時,就會立即執行,而不像一般的函式需要呼叫才會執行
箭頭函數的限制
this 指向的是 callback 函數,而非物件,所以箭頭函式可當成無法用 this。
箭頭函式無法用於建構式(constructor),使用new會產生錯誤。
只有單一個傳入參數時,括號可以不用。
Last updated
Was this helpful?