函式
基本概念
-
在JS中,函式實際上是物件,是
Function型別的實體, -
函式名是指向函式物件的指標,
function sum(num1, num2){
return num1 + num2;
}
// 檢查sum是否是Function型別的實體
console.log(sum instanceof Function); // true
let anotherSum = sum; // 指向同一個函式
console.log(anotherSum(1,2)); // 3
- 函式將若干條陳述句封裝起來,可以提高代碼的可復用性,
創建函式
函式宣告
語法:
function funcName(params){
// do something...
return something;
}
函式運算式
語法:
let funcName = function(params){
// do something...
return something;
}
因為函式本質上是物件,所以可以直接賦值給一個變數,這個變數將指向這個函式,呼叫函式時直接使用變數名即可,
箭頭函式
語法:
let funcName = (params)=>{
// do something...
return something;
}
注:箭頭函式是ES6新加入的語法,
建構式
語法:
let funcName = new Function("param1","param2",...,"body");
建構式接收任意多個字串引數,最后一個是函式體,前面的是函式引數,
注:這種寫法不推薦,因為作為JS陳述句,它首先會被當做常規代碼決議,然后再通過Function建構式決議形成函式物件,性能較差,
箭頭函式
箭頭函式是ES6新增的語法,任何可以使用函式運算式的地方,都可以使用箭頭函式,
語法格式
- 如果沒有引數,要寫括號:
let getRandom = () => {return Math.random();};
- 如果引數只有一個,可以不寫括號:
let double = x => {return x*2; };
- 如果有多個引數,要寫括號:
let sum = (x, y) => {return x + y; };
- 如果函式體有多條陳述句,則需要大括號:
let division = (a, b)=>{
if(b === 0){
console.error("除數不能為零");
}else{
return a/b;
}
}
- 如果函式體只有一條陳述句,可以不寫大括號,此時會隱式回傳這行代碼的值:
let double = x => x*2;
特點
-
箭頭函式語法簡潔,
-
箭頭函式不能使用
arguments、super,也不能用作建構式,且箭頭函式沒有prototype屬性,
引數串列
JS的函式引數和大多數其他語言不同,JS中的函式引數定義是無關緊要的,
假如定義函式時預設有兩個引數,而呼叫時傳入了0個、1個或者3個引數,解釋器都不會報錯,
原因是使用function關鍵字定義的函式,可以在函式內部訪問arguments物件,從中獲取傳入的引數,
function testArgs(){
console.log(arguments);
}
testArgs(1,2,3,4,5,6);
testArgs(1,"Hello",true);
arguments是一個類陣列物件,它并不是Array的實體物件,并不是真正的陣列,但是它具有類似陣列的一些操作,比如可以像陣列一樣通過[]訪問元素的值,可以通過length獲取元素個數,
可以通過arguments[0]訪問到傳入的第一個引數,通過arguments.length獲取傳入多少個引數,
箭頭函式的引數
注:箭頭函式不能使用arguments,所以箭頭函式需要多少引數需要在定義函式時就寫明,
不存在函式多載
在其他語言比如C++、Java中,存在函式多載,即可以存在多個函式名相同的函式,只要它們的引數個數、引數型別不一樣,在呼叫函式的時候,會根據傳入的引數資料型別,匹配上對應的函式,
顯然,在JS中,函式的引數串列是隨意的(引數個數與引數資料型別都是隨意的),也就不存在函式多載了,
注:在JS中,如果有多個函式名相同的函式定義,只有最后一個是有效的,前面的定義都將被覆寫,
默認引數值
// 回傳一個由隨機陣列成的陣列,默認長度為5
function getRandomArray(length = 5){
const arr = new Array();
for(let i=0;i<length;i++){
arr.push(Math.floor(Math.random()*100));
}
return arr;
}
const arr1 = getRandomArray();
console.log(arr1);
//[76, 86, 60, 21, 37]
const arr2 = getRandomArray(10);
console.log(arr2);
//[18, 98, 76, 43, 77, 24, 44, 74, 58, 3]
- 在函式引數后面使用
=就可以為其設定默認值,
函式宣告和函式運算式
-
函式宣告指通過
function functionName(){}來得到一個函式. -
函式運算式是指通過
function(){}創建一個匿名函式,再講這個匿名函式賦值給一個變數functionName.
區別
函式宣告提升
所有函式宣告在JS引擎執行代碼之前會被提升到代碼頂部,即以下兩段代碼是等價的,
console.log(sum(1,2)); // 不會報錯,因為sum會被提升到頂部
function sum(x,y){
return x+y;
}
function sum(x,y){
return x+y;
}
console.log(sum(1,2));
而函式運算式不會被提升:
console.log(sum(1,2)); // 報錯
let sum = function(x,y){
return x+y;
}
sum作為一個變數:
-
如果使用
var宣告會被提升,但是定義不會被提升,undefined無法被呼叫; -
如果使用
let則宣告和定義都不會被提升,一個未宣告的變數顯然無法被呼叫,
函式作為值
函式名是一個變數,因此函式可以作為函式引數傳遞給另一個函式,并且函式也可以作為一個函式的回傳值,
回呼函式
如果當前無法決定呼叫哪個函式,可以先把函式作為引數傳遞,等到可以做出明確的選擇時,再回過頭來呼叫這個函式,這種情況下作為引數傳遞的函式就被叫做回呼函式(callback).
典型應用
向后端介面發送網路請求時,一般會附帶上兩個回呼函式,一個success函式,一個error函式,在發送網路請求時,是無法確定請求是否發送成功的,只有拿到了回傳結果,才能確定執行success函式或error函式,
閉包
閉包是指參考了另一個函式作用域中變數的函式,通常在嵌套函式中實作,
// 獲取累加器
function getAccumulator(){
let num = 0; // 內部屬性
return function(){ // 回傳一個函式
return num++;
}
}
// 呼叫函式獲取累加器
let add = getAccumulator();
console.log(add()); // 0
console.log(add()); // 1
console.log(add()); // 2
console.log(add()); // 3
console.log(add()); // 4
在函式getAccumulator的作用域中,有一個num屬性,而回傳的函式中,參考了這個num. 即回傳的這個函式參考了另一個函式作用域中的變數.
num這個變數和add函式系結在了一起,當getAccumulator執行結束后也不會被回收,并且無法被直接訪問,
立即呼叫的函式
立即呼叫的函式運算式(IIFE, Immediately Invoked Function Expression)
ES5沒有塊級作用域,可以使用立即呼叫的函式運算式來模擬塊級作用域,
var funcName = function(){...};
funcName();
使用立即呼叫的函式運算式可以省略一個不必要的函式名,
(function(){
...
})();
ES6之后,IIFE就沒有那么必要了,因為可以很方便地使用塊級作用域,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/529978.html
標籤:JavaScript
上一篇:什么是虛擬DOM?
