函式

  • 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?