1 函數(shù)
1.1 什么是函數(shù)
- 函數(shù)就是具有特定功能的代碼塊,可以被多次調(diào)用
- 函數(shù)是 JavaScript 中的一種數(shù)據(jù)類型,屬于對(duì)象類型; 使用
typeof判斷可以返回function
1.2 函數(shù)的組成
- 函數(shù)名: 函數(shù)名本質(zhì)上是個(gè)變量,函數(shù)名的命名規(guī)則與變量名的命名規(guī)則一致。
- 參數(shù): 參數(shù)本質(zhì)上是個(gè)變量,只能在函數(shù)內(nèi)使用,在調(diào)用函數(shù)的時(shí)候才能被賦值。
- 函數(shù)體: 用大括號(hào)包裹的代碼塊。
- 返回值:返回值是函數(shù)的計(jì)算結(jié)果, 作為函數(shù)調(diào)用表達(dá)式的值
1.3 聲明函數(shù)
① function 關(guān)鍵字方式
function 函數(shù)名() {
函數(shù)體語句 ...;
}
function 函數(shù)名(參數(shù)列表...) {
函數(shù)體語句 ...;
}
② 表達(dá)式方式
var 函數(shù)名 = function() {
函數(shù)體語句 ...;
}
var 函數(shù)名 = function(參數(shù)列表...) {
函數(shù)體語句 ...;
}
1.4 函數(shù)調(diào)用和返回值
① 函數(shù)調(diào)用
-
函數(shù)名()才是函數(shù)調(diào)用,函數(shù)體語句才能執(zhí)行,才能得到函數(shù)的返回值。 - 函數(shù)名后面沒有括號(hào),就是在使用一個(gè)變量,函數(shù)體語句不會(huì)執(zhí)行,也得不到函數(shù)的返回值。
② 返回值
1. 返回值是函數(shù)的計(jì)算結(jié)果,是函數(shù)調(diào)用表達(dá)式的值(函數(shù)名加括號(hào)就是函數(shù)調(diào)用表達(dá)式)
var res = fn(); // 把函數(shù)的返回值賦值給變量 res
fn() + 100; // 函數(shù)的返回值與 100 相加
console.log(fn()); // 輸出函數(shù)的返回值
2. 通過 return 關(guān)鍵字定義函數(shù)的返回值
return 需寫在函數(shù)體內(nèi),return 右邊需寫一個(gè)表達(dá)式(變量、直接量、帶運(yùn)算符的表達(dá)式), 表達(dá)式的值就是函數(shù)的返回值。
如果 return 右邊是空的,函數(shù)沒有返回值, 沒有返回值函數(shù)調(diào)用表達(dá)式的值會(huì)自動(dòng)得到 undefined
3. return 還可以結(jié)束函數(shù)的執(zhí)行; 一旦執(zhí)行到 return,后面的語句就不會(huì)執(zhí)行了。
1.5 函數(shù)的參數(shù)
①形參和實(shí)參
形參:函數(shù)聲明時(shí)設(shè)置的參數(shù),相當(dāng)于沒有賦值的變量,必須以變量名的形式給出。
實(shí)參:調(diào)用函數(shù)時(shí)所給的參數(shù),用于給形參賦值, 可以是變量、直接量、表達(dá)式等形式。
② 形參和實(shí)參的數(shù)量問題
標(biāo)準(zhǔn)情況下,形參和實(shí)參的數(shù)量應(yīng)一致,按順序賦值,如果:
形參數(shù)量 > 實(shí)參數(shù)量:后面的形參沒有被賦值,自動(dòng)得到 undefined。
形參數(shù)量 < 實(shí)參數(shù)量:多余的實(shí)參則沒有用。
③ 形參的默認(rèn)值(可選參數(shù))
- 具有默認(rèn)值的參數(shù)即可選參數(shù)
- 可選參數(shù)應(yīng)放在必選參數(shù)的后面,因?yàn)閷?shí)參按順序給形參賦值,不給實(shí)參則可以返回默認(rèn)值。
ES5 規(guī)范中設(shè)置默認(rèn)值的方式:
function fn(name, age) {
// 如果 age 沒有對(duì)應(yīng)的實(shí)參, 設(shè)置一個(gè)默認(rèn)值
if (age === undefined) {
age = 默認(rèn)值;
}
}
ES6 規(guī)范中的設(shè)置默認(rèn)值的方式:
funciton fn(name, age=默認(rèn)值) {
}
④ arguments關(guān)鍵字
- arguments 是系統(tǒng)定義好的變量,可以直接使用,但只能在函數(shù)內(nèi)使用, 在函數(shù)外使用則會(huì)報(bào)錯(cuò)。
- arguments 是個(gè)偽數(shù)組對(duì)象,里面的成員是函數(shù)調(diào)用時(shí)傳進(jìn)來的實(shí)參; arguments 具有l(wèi)ength 屬性,可以通過索引獲取到其中的每個(gè)成員。
- arguments 是除了形參之外另外一種獲取實(shí)參的方式。 形參只能獲取固定數(shù)量的實(shí)參,arguments 可以獲取所有的實(shí)參。
- 使用 arguments 可以定義可變參數(shù)數(shù)量的函數(shù)。
// 計(jì)算所有參數(shù)的和,返回結(jié)果
function sumFn() {
// 定義變量 記錄和
var sum = 0;
// 遍歷 arguments
for (var i = 0; i < arguments.length; i ++) {
sum += arguments[i];
}
// 返回結(jié)果
return sum;
}
1.6 作用域
① 變量的作用域
作用域即變量的可作用范圍,根據(jù)作用域不同,變量可分為全局變量和局部變量。
全局變量: 在函數(shù)以外定義,作用域是全局。如:函數(shù)外聲明的函數(shù),函數(shù)內(nèi)沒有用var聲明的變量。
局部變量: 在函數(shù)內(nèi)定義,作用域是所在的函數(shù)。如:函數(shù)的形參,函數(shù)內(nèi)聲明的函數(shù)。
- 函數(shù)名本質(zhì)上是變量,所以函數(shù)本身也有作用域,由函數(shù)是在哪里聲明的決定。
- 如果在函數(shù)里不使用var聲明變量,該變量是全局的(嚴(yán)格模式下不允許不使用var聲明的變量的)
② 作用域鏈
函數(shù)里還可以繼續(xù)聲明函數(shù),函數(shù)的嵌套關(guān)系形成了作用域鏈,函數(shù)內(nèi)可以使用本層作用域和上層作用域中的變量。
作用域鏈描述變量查找的過程:
當(dāng)使用某個(gè)變量的時(shí)候,先從本作用域中查找,如果找不到就去上層作用域查找,哪里找到哪里停止,找不到則繼續(xù)向上查找,直到全局作用域,如果仍然沒有查找到該變量,則報(bào)錯(cuò)。
注:變量的作用域只與函數(shù)聲明的位置有關(guān)系,與函數(shù)在哪里調(diào)用無關(guān)。
1.7 變量提升
① 變量提升
- 代碼正式執(zhí)行之前,會(huì)進(jìn)行預(yù)解析,預(yù)解析時(shí)會(huì)把變量提升到本作用域的最前面(只創(chuàng)建了變量,卻沒有賦值)
- 全局變量在整個(gè)代碼正式執(zhí)行之前就發(fā)生了提升
- 局部變量在函數(shù)體語句執(zhí)行之前進(jìn)行提升
② 函數(shù)提升
- 函數(shù)名本質(zhì)上就是變量,所以函數(shù)也會(huì)提升到本作用域的最前面。
- 使用 function 關(guān)鍵字形式聲明的函數(shù),提升比較徹底,代碼執(zhí)行之前不但創(chuàng)建了函數(shù)名并且有值。
- 使用表達(dá)式方式聲明的函數(shù),提升規(guī)則與普通變量沒有差別。
- 函數(shù)提升與變量提升的區(qū)別:
① 函數(shù)提升更徹底
② 正式執(zhí)行代碼的時(shí)候,執(zhí)行到變量聲明并賦值的語句會(huì)進(jìn)行賦值操作, 執(zhí)行到函數(shù)聲明語句會(huì)跳過
1.8 匿名函數(shù)
即沒有名字的函數(shù),用函數(shù)這種數(shù)據(jù)類型的直接量表示,適合作為自調(diào)用函數(shù)和回調(diào)函數(shù)。
1.9 自調(diào)用函數(shù)(立即執(zhí)行的函數(shù))
函數(shù)聲明完立即被調(diào)用,主要作用是用來產(chǎn)生作用域,避免全局變量污染。一般以匿名函數(shù)作為自調(diào)用函數(shù),有名字的函數(shù)也可以作為自調(diào)用函數(shù),但沒有必要。
// 匿名的自調(diào)用函數(shù)(立即執(zhí)行的函數(shù))
(function() {
函數(shù)體語句;
})();
// 有名字的自調(diào)用函數(shù)
(function fn() {
函數(shù)體語句;
})();
// 匿名的自調(diào)用函數(shù) 設(shè)置參數(shù)
(function(形參1, 形參2) {
函數(shù)體語句;
})(實(shí)參1, 實(shí)參2);
1.10 回調(diào)函數(shù)
具有以下三個(gè)條件的函數(shù)稱為回調(diào)函數(shù):
- ① 函數(shù)是我定義的
- ② 我沒有直接調(diào)用該函數(shù)
- ③ 函數(shù)卻執(zhí)行了
注意: 回調(diào)函數(shù)大部分情況會(huì)作為其他函數(shù)(或方法)的參數(shù)。
1.11 遞歸函數(shù)
函數(shù)內(nèi)部再次調(diào)用自己。
① 遞歸成功的條件:
- 有明確的結(jié)束遞歸的條件
- 有一個(gè)趨向于結(jié)束遞歸調(diào)用的趨勢(shì)
② 遞歸函數(shù)的缺點(diǎn)
- 可能發(fā)生內(nèi)存泄漏
- 效率不高
③ 遞歸函數(shù)應(yīng)用場(chǎng)景
- 后端的目錄操作(刪除、復(fù)制、剪切)
- 前端對(duì)后端數(shù)據(jù)進(jìn)行遞歸處理