函式的定義與引數
JavaScript 作為函式式語言來理解。
關鍵概念
函式是第一類物件(一等公民)
函式可以看作是 其他任意型別的 Javascript 物件
函式和其他的資料型別一樣,能被變數引用,以字面量形式宣告,作為函式引數傳遞
發現
:musical_note: 在需要呼叫某函式的位置 定義該函式,能讓程式碼更緊湊、更易懂
術語
一等公民
一般來說,如果某程式設計語言中的一個值可以作為 引數傳遞
,可以從 子程式中返回
,可以 賦值給變數
,就稱為一等公民
二等公民
可以作為 引數傳遞
,但是不能從子程式中返回,也不能賦值給變數
三等公民
值連作為引數傳遞都不行(label)
3.1 函式式的不同點
與物件的不同
物件的常見功能
-
物件可通過字面量來建立
{}
var lsObj = {}; 複製程式碼
-
物件可以賦值給變數、陣列項,或其他物件的屬性
var lsObj = {}; lsArray.push({}); lsObj.data = {} 複製程式碼
-
物件可以作為引數傳遞給函式
function hide(obj){ obj.visibility = false; } hide({}); 複製程式碼
-
物件可以作為函式的返回值
function returnNewLs(){ return {}; } 複製程式碼
-
物件能夠具有動態建立和分配的屬性
var lsObj = {}; lsObj.name = "lisi"; 複製程式碼
函式是第一類物件
函式擁有物件的所有能力,所以函式可被看作 任意其他型別 的物件
函式也具有物件的功能
-
通過字面量建立
function ninjaFunction(){} 複製程式碼
-
賦值給變數、陣列項或其他物件的屬性
var ninjaFunction = function(){}; //為變數賦值一個新函式 ninjaArray.push(function(){}); //向陣列中增加一個新函式 ninja.data = function(){}; //給某個物件的屬性賦值一個新函式 複製程式碼
-
作為函式的引數傳遞
function call(ninjaFunction){ ninjaFunction(); } //新函式作為引數傳遞給函式 call(function(){}); 複製程式碼
-
作為函式的返回值
//返回一個新函式 function returnNewNinjaFunction(){ return function(){}; } 複製程式碼
-
動態建立的屬性
//為函式增加一個新屬性 var ninjaFunction = function(){}; ninjaFunction.ninja = "Hanzo"; 複製程式碼
:eight_pointed_black_star: 函式也是物件,函式與物件的不同在於:==函式是可呼叫的==
:v: 第一類物件的特點之一:能夠作為引數傳入函式
對於函式來說這個特性表明:將某個函式作為引數傳入另一個函式,傳入的函式會在將來的某個時刻執行。由此推出 【回撥函式】
回撥函式
瀏覽器的回撥函式(計時器函式)和我們自定義的回撥函式
回撥不一定是非同步的
瀏覽器回撥
document.body.addEventListener("mousemove",function(){...})
複製程式碼
自定義的回撥
排序方法sort,可以傳入一個函式進行排序
var values = [0,3,2,7,1,8];
values.sort(function(value1,value2){
return value1 - value2;
});
複製程式碼
? 函式式方式 把 函式當作一個 單獨實體 來建立,與其他型別一樣,建立、作為引數傳遞和返回。函式顯示了一等公民的地位。
function(value1,value2){}
是一個整體,類似 abc
等
3.2 函式作為物件
類似物件,函式也可以新增屬性
//物件
var ninja = {};
ninja.name = 'hitsuke';
//函式
var wieldSword = function(){};
wieldSword.swordType = "katana";
複製程式碼
儲存函式
函式的屬性作為值
:question: 管理一個元素的所有回撥函式集合,相同的回撥只儲存一次
//儲存唯一函式集合
var store = {
nextId : 1,
cache : {},
add : function(fn){
if(!fn.id){
fn.id = this.nextId++;
this.cache[fn.id] = fn;
return true;
}
}
}
function ninja(){}
store.add(ninja); //true ninja.id 存在了
//Object.getOwnPropertyNames(ninja) (6) ["length", "name", "arguments", "caller", "prototype", "id"]
store.add(ninja); //undefined
複製程式碼
快取結果
函式的屬性作為物件
//計算先前得到的值
function isPrime(value){
if(!isPrime.answers){
isPrime.answers = {}; //建立快取
}
if(isPrime.answers[value] !== undefined){
return isPrime.answers[value]; //檢查快取的值 並 返回
}
var prime = value !== 0 && value !== 1;
for(var i = 2;i < value; i++){
if(value % i === 0){
prime = false;
break;
}
}
return isPrime.answers[value] = prime; //儲存計算的值
}
isPrime(5);
isPrime.answers[5];
複製程式碼
3.3 函式定義
JavaScript 定義函式的幾種方式
-
函式宣告和函式表示式
function abc(){} var abc = function(){} 複製程式碼
-
箭頭函式 lambda函式
myArg => myArg * 2 複製程式碼
-
函式建構函式
new Function('a','b','return a + b') 複製程式碼
-
生成器函式
//函式退出再進入時,之前的變數值被儲存 function* myGen(){ yield 1; } 複製程式碼
函式宣告和函式表示式
//函式宣告強制以 function 開頭;作為一個單獨的JavaScript語句,函式宣告必須獨立
function samurai(){
return "samurai here";
}
function ninja(){
function hiddenNinja(){
return "ninja here";
}
return hiddenNinja();
}
複製程式碼
//函式表示式 作為 賦值表示式的右值 、作為其他函式的引數
var myFunc = function(){};
myFunc(function(){
return function(){};
});
複製程式碼
對於函式宣告來說,函式名是強制性的,對於函式表示式來說,函式名是可選的。
立即執行函式
一般包裹在一對括號內:JavaScript解析器必須輕易區分 函式宣告和函式表示式的區別。
函式表示式放在括號內,為JavaScript解析器指明:它正在處理一個函式表示式而不是語句。
myFunctionName(3);
//IIFE 立即函式
(function(){})(3)
(function namedFunctionExpression(){})(); //立即呼叫
//函式表示式作為一元操作符的引數立即呼叫
//為JS引擎指明 處理的是表示式,而不是語句
+function(){}();
-function(){}();
!function(){}();
~function(){}();
複製程式碼
箭頭函式
箭頭函式是函式表示式的簡化版
//箭頭函式的語法
//箭頭函式接收一個引數並返回表示式的值
param => expression
//如果沒有引數或多於一個引數,引數列表必須包裹在括號內
//如果只有一個引數,括號不是必須的
var greet = name => "Greeting " + name;
var greet = () => "Greeting";
var greet = (name,age) => "hello " + name + age;
//胖箭頭 操作符後面可以是 表示式 也可以是程式碼塊
var greet = name => "Greeting" + name;
var greet = (name,age) => {
return name + age;
}
複製程式碼
var values = [1,2,3,5,8];
values.sort(function(value1,value2){
return value1 - value2;
});
//箭頭函式
values.sort((value1,value2) => value1 - value2);
複製程式碼
3.4 函式的實參和形參
如果函式的 實引數量 > 形引數量 , 多餘的不會分配給形參
如果函式的 實引數量 < 形引數量 , 對應的形參賦值為 undefined
剩餘引數
只有函式的最後一個引數才能是剩餘引數。
給函式的最後一個形參加上省略號(…)字首,這個引數就變成了一個 剩餘引數的陣列 。陣列內包含著傳入的剩餘的引數。
function multiMax(first, ...remainingNumbers){
...
}
複製程式碼
預設引數
為函式的引數提供一個預設引數
預設引數可以是任意值:數字、字串、物件、陣列、甚至是函式
後面的預設引數 可以引用 前面的預設引數
function performAction(ninja, action){
action = typeof action === "undefined" ? "skulking" : action;
return ninja + " " + action;
}
function performAction(ninja, action = "skulking"){
return ninja + " " + action;
}
function performAction(ninja, action = "skulking", message = ninja + " " + action){
return message;
}
複製程式碼
typeof 操作符返回一個字串 用於表明運算元的型別。如果運算元未定義,則返回字串 "undefined"