學習目標:函式是什麼,有分成哪幾種用法;參數和引數的區別;return 是什麼?常用的內建函式有哪些。
關於學習 JavaScript 的心得,主要源自於以下學習資源:
將操作變成一項功能,好比我們把 深蹲、弓箭步、跪姿抬腿、交叉跳 這些動作集合起來,就變成了一項臀部訓練,當我們每次要重複執行這些動作時,就會執行臀部訓練。
以網頁功能做說明的話,當 User 在登入或註冊有錯誤時,我們需要一個好看的提示視窗,我們可以透過函式去調用。
之前所使用到的 alert(message)
、prompt(message,[default])
、comfirm(qusestion)
,這些都是內建的 function 。
函式通常會包含以下三個部分
name
:函式的名稱。#也可能沒有()
:中括號,是執行函式的意思,括號之間可以放入參數 (Argument),參數跟參數間會用,
隔開。 #也可以不放入參數{}
:大括號,會將要重複執行的程式放入此區塊中。
function name() { //執行區塊}
- 舉例
function showMessage() { alert( 'Hello world !' );}
函式的命名
跟變數一樣,需要有語意的命名,通常會以動詞作為前綴搭配命名:
'get…'
回傳某值'calc…'
計算某些內容'create…'
創建某些內容'is…'
檢查某些內容回傳 boolean
定義函式
常見函式有三種。#由於中文翻譯有太多因此都放在後方供大家辨認
- Function Declaration(函式陳述式、函式宣告、函數聲明)
- Function Expressions(函式表達式、函式運算式、函數表示式)
- Function Constructors(函數建構子)
以下分別詳細說明:
Function Declaration
- 這是最常見的種類
- 不會回傳值但會做其他的事情。
- 舉例:
function name() { //執行區塊}
Function Expressions
- 是輸入後能夠直接回傳值的一串程式。
- 舉例:將變數賦予一個函式
變數 = function ([參數]){ … };
let anonymousGreet = function(){ console.log('hi');};
Function Constructors
- 透過
new Function
的方式建立函式。 #F 需要大寫 - 舉例:
let square = new Function('number', 'return number * number');
- 其他說明
[補充說明]實務上較少使用函數建構子的原因透過此方式建立的函式物件,每次執行時都會進行解析「字串」(如 'return number * number' ) 的動作,運作效能較差,所以通常實務上較少使用這種方式建立函式。
調用函式
也就是執行函式,可以通過名稱調用
Function Declaration
- 在函式名稱後方加上中括號
- 舉例:我們調用了兩次,因此會 alert 2 次
function showMessage() { alert( 'Hello world !' );}showMessage();showMessage();
Function Expressions
- 在變數名稱後方加上中括號
- 舉例:
let anonymousGreet = function(){ console.log('hi');};//執行 Function Expressionsconsole.log( anonymousGreet ); //打印出函式程式碼console.log( anonymousGreet() ); //打印出函式 value//#在其他的語言中只要提到函式的名稱,就會立即執行,但 JavaScript 需要透過中括號來執行//我們也可以將 變數賦予變數 來執行函式let greeting = anonymousGreetgreeting();
匿名函式(Anonymous Function)
在一開始有說到函式通常會有名字,但其實我們剛剛就已經使用到了匿名函式在 Function Expressions 的時候,我們用變數名稱取代了函式的名稱。
- 沒有
name
的函式 - 舉例:將變數賦予一個函式
變數 = function ([參數]){ … };
let anonymousGreet = function(){ console.log('hi');};
變數的值為匿名函式,用變數名引用執行。
參數 Parameter 與引數 Argument
先直接用範例來進行說明
function showGreeting(name , greeting) { alert( name + greeting );}let woman = 'Marry';let chineseGreeting = '你好.function showGreeting(woman, chineseGreeting);
- 參數:
name
、greeting
。 - 引數:
woman
、chineseGreeting
。
所以我們可以知道…
參數 為一開始設定的值。
引數 為實際引用進來的值。
參數傳入 function
- 舉例1. confirm + if 條件式
function ask(question, yes, no) { if(confirm(question)) { yes(); } else { no(); }}function yesAnswer() { alert("歡迎蒞臨網站");}function noAnswer() { alert("抱歉,本網站禁止未成年人造訪");}ask('您是否已成年?', yesAnswer, noAnswer);
將
yesAnswer
與noAnswer
傳入ask
內,依據 if 條件式做判斷執行。
- 舉例2. 陣列+迴圈
function transform(arr, cale) { var result = []; for(var i = 0; i < arr.length; i++) { var value = cale(arr[i]); result.push(value); } return result;}function double(x){ return x*2}function triple(x) { return x*3;}console.log(transform([1,2,3], double)); //2,4,6console.log(transform([1,2,3], triple)) ; //3,6,9
也可以用 匿名函式 直接傳入參數,更直覺
function transform(arr, cale) { var result = []; for(var i = 0; i < arr.length; i++) { var value = cale(arr[i]); result.push(value); } return result; }console.log(transform([1,2,3], function(x) { return x*2 })); //2,4,6console.log(transform([1,2,3], function(x) { return x*3 })); //3,6,9
設定參數卻未傳入
- 如果未參數傳入值,則會回傳 默認值
undefind
- 舉例
function showGreeting( name , greeting){ alert( name + greeting );}//greeting 參數未傳入值showGreeting( 'Mia' ); // Miaundefined
- 為了避免回傳 undefined,我們可以
if
、||
自訂成參數的默認值
//使用 iffunction showGreeting( name , greeting){ if( greeting === undefined ){ greeting = ' no text given' } alert( name + greeting );}
// 使用 ||function showGreeting( name , greeting){ greeting = greeting || ' no text given'
//greeting 等於 false 則會得到默認值 可參考:邏輯運算符alert( name + greeting );
- 其他補充說明
[補充說明] ES6 提供的新做法function showGreeting( name , greeting = ' no text given'){ alert( name + greeting );}//greeting參數未傳遞function showGreeting( Mia ); // Mia no text given’
- 有關於到底是傳什麼,可參考:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?、從博物館寄物櫃理解變數儲存模型
- 克服奇怪的JavaScript 線上課程有提到:
所有純值都是 by value
所有的物件都是 by reference
return(回傳)
- 可以透過
return
這個指令回傳調用函式的一個值 - 當執行時,函式就會停止(後面的程式直接不執行),並回傳 value。
- 可以在函式的任意位置。
- 可能會在函式中出現很多次。
- 也可以沒有返回。#將會回傳
undefined
- 舉例
function calcSum(a, b){ return(a + b);}calcSum(1,2); //3
「回傳」與「印出」的差異
- 以例子解釋
function add(a, b) { console.log( a + b );}add(1,2)
function add(a, b) { console.log( a + b );}console.log( add(1,2) );
這就是一開始說的 return
可加可不加,不加的話會回傳默認值 undefind
。
呼叫函式最重要的就是要回傳東西作後續的執行。
通常是針對回傳的東西做測試,因此最常見的寫法應該如下
function add(a, b) { return a + b ;}console.log( add(1,2) ); //針對回傳的東西做測試
內建函式
數學相關函式
Math.ceil()
:無條件進位。Math.floor()
:無條件捨去。Math.round()
:四捨五入。Math.random
:產生 0 ~ 1 的隨機數( 不包括 1 )。
請寫一個 function getRandomInt 接收一個數字 max ,並回傳隨機 1 ~ n 其中一個數字function getRandomInt(max) { var result = 0; result = Math.floor(Math.random()*Math.floor(max)+1); return result;}getRandomInt(17);
Math.max(num1, num2, num3)
:丟入一系列數字,回傳最大值Math.min(num1, num2, num3)
:丟入一系列數字,回傳最小值
#丟入陣列用法:Max.max(…arr)
、Min.max(…arr)
var numbers = [1, 2, 3, 4];Math.max(…numbers) // 4Math.min(numbers) // 1
Number.MAX_VALUE
:回傳 JavaScript 能存的最大數字Number.toFixed(x)
:取到小數點後第 x 位數( 無條件捨去 )Math.sqrt()
:開根號Math.log()
:對數Math.pow(x, y)
:次方運算Marh.PI
:圓周率
字串、數字間互相轉換
- 字串轉數字:
parseInt(<string>, x)
Number(<string>)
parseInt("20",10) //x 為進位方式 default 10 進位Number("20")
- 數字轉字串:
<number>.toString()
<number> + ""
var num = 20num.toString();num + ""
字串相關函式
toLowerCase()
:變小寫toUpperCase()
:變大寫:indexOf(keyword)
:檢查字串是否存在
1. 有,回傳 keyword 索引值
2. 沒有,回傳-1
replace(x, y)
:替換字串。 #若有多個相同的字串,只會替換第一個
var str = 'apple banana orange'str.replace('a', 'q')
trim()
:去掉空格。length
:回傳長度。charCodeAt(char)
: 取出字元的 ASCII 碼。String.fromCharCode(num)
: 將 ASCII 碼轉成字元。
字串、陣列間互相轉換
- 字串轉陣列:
split(separator, howMany)
#常用於 CSV
var str = 'How are you doing today?'str.split(' ',2); // [How, are]
- 陣列轉字串:
arr.join('')
var array = [How, are, you, doing, today, ?]str.join(''); // 'How are you doing today?'
陣列相關函式
push()
:添加元素到陣列的最末端,並 return 陣列的新長度。fill()
:填入值。Arry(n)
:n
= 陣列長度,創造n
長度一個陣列。map(function)
:將每個元素傳入函式中,並 return 新的陣列。
var arr = [1, 2, 3]function double(x) { return x*2;}console.log(arr.map(double));
filter(function)
:將每個元素傳入函式中,符合條件(true)留下,不符合(false),並 return 新的陣列。
var arr = [11, -2, 23, -5, 4, -7]function positive(x) { return x > 0;}console.log(arr.filter(positive)); //[11, 23, 4]
slice(index, index)
:擷取陣列某個部分,第 index[] 到 第 index[] 之前,並 return 新的陣列。
var arr = [1, 2, 3, 4, 5, 6]console.log(arr.slice(3)); //4, 5, 6console.log(arr.slice(3, 4)); //4console.log(arr.slice(3, 5)); //4, 5
splice(star [, deleteCount[, item1[, item2[, ...]]]])
:改變原本的陣列 插入元素跟刪除元素。
var arr = ['a', 'b', 'c', 'd', 'e', 'f']arr.splice(3, 1, ‘x’);console.log(arr);
sort
:改變原本的陣列的順序。reduce
:
- 字串:依據 Unicode 編碼位置(code points)而定。
const months = ['March', 'Jan', 'Feb', 'Dec'];months.sort();console.log(months);// expected output: Array ['Dec', 'Feb', 'Jan', 'March']
2.數字:依據 Unicode 編碼位置(code points)而定,並不是依據大小。
var arr = [11, -2, 23, -5, 4, -7]arr.sort();console.log(arr); // [-2, -5, -7, 11, 23, 4]
改成依據大小
var arr = [11, -2, 23, -5, 4, -7]//由小到大arr.sort(function(a, b){ return a-b;})console.log(arr); // [-2, -5, -7, 11, 23, 4]//由大到小arr.sort(function(a, b){ return b-a;})console.log(arr); // [23, 11, 4, -2, -5, -7]
- some():傳入一個函式表達式,檢查陣列中的是否至少有一個元素,通過該函式表達式,此方法回傳為 Boolean
var arr = [11, -2, 23, -5, 4, -7]var hasNegative = function(element) { return element < 0 }console.log(arr.some(hasNegative) // true