前言
Js
中的函式其實相較於其他語言是比較複雜的,光函式型別就分了好幾種,其中this
指向更是讓很多初學者摸不到頭腦。
那麼本篇文章將著重介紹一下函式的基本使用,關於this
指向的詳解將放在下一章。
函式的作用其實就是將一段可重複利用的程式碼進行整合,方便多次使用。
一定要注意,先宣告定義函式而後再進行使用。這是一種規範。
函式定義
例項定義
在Js
中函式是Fuction
類的例項物件,因此我們可以用例項化的方式來定義函式,這也能充分理解函式也是物件這一概念。
<script> "use strict"; // 引數1:形參,引數2:函式程式碼體 let func = new Function("title","console.log(title)"); func("雲崖先生的部落格"); </script>
標準定義
使用Function
類的方式定義函式太過麻煩,因此推薦使用function
標準語法進行定義。
<script> "use strict"; function func(title){ console.log(title); } func("雲崖先生的部落格"); </script>
物件字面量
我們可以在一個物件中定義函式,這通常會被稱之為物件方法。
<script> "use strict"; let obj = { description:"這是一個物件屬性", show:function(title){ console.log("這是一個物件方法,傳入的引數是:",title); }, } obj.show("雲崖"); </script>
匿名函式
全域性宣告的標準定義函式會被存入window
物件中,這樣做會產生很多弊端。
因為我們的函式名如果不恰當的話可能造成window
方法缺失。
<script> "use strict"; function func(title){ console.log(title); } func("雲崖先生的部落格"); console.log(window.func); // 有的 </script>
因此,可以通過賦值來進行匿名函式的定義,定義前使用let/const
進行宣告,這樣就不會壓入至window
物件中,注意後面要以;
結束。 注意:以var
宣告的匿名函式會壓入至window
物件中
<script> "use strict"; let func = function (title) { console.log(title); }; func("雲崖先生的部落格"); console.log(window.func); // undefined </script>
函式執行
函式提升
標準定義的函式會進行函式提升,可以先使用後定義,這是不符合規範的。
但是匿名函式不會進行函式提升。
函式的提升是排在var
變數提升之前的,因此如果函式名與用var
定義的變數重複那麼該名字會被變數拿到,函式則會被當做垃圾回收。
即使使用了
var
來定義匿名函式,也不會進行函式提升, 但是會將該函式壓入window
物件中,所以建議使用let/const
來對匿名函式進行接收。
標準宣告函式會進行提升
<script> "use strict"; func("雲崖先生的部落格"); // 執行了 function func (title) { console.log(title); } console.log(window.func); // 有的 </script>
匿名函式不會進行提升
<script> "use strict"; func("雲崖先生的部落格"); // Uncaught ReferenceError: Cannot access 'func' before initialization let func = function (title) { console.log(title); } console.log(window.func); </script>
自執行函式
在很早之前,如果你寫了一個Js
模組,為了防止全域性作用域的汙染,你會將程式碼放入一個自執行函式裡面。
但是現在不用了,因為let/const
具有塊作用域,它們的出現決定我們今後寫的模組不用再拿自執行函式來進行封裝了。
首先來看一下自執行函式怎麼使用。
<script> "use strict"; (function (title) { console.log(title); // 自己執行 })("雲崖先生的部落格"); // 這裡呼叫 </script>
自執行函式封裝
(function () { function show() { console.log("執行了show功能"); } function test() { console.log("執行了test功能"); } window.module = { show, test }; })();
let
作用域封裝
{ let show = function () { console.log("執行了show功能"); } let test = function () { console.log("執行了test功能"); } window.module = { show, test }; };
呼叫
<script src="JavaScript.js"></script> <script> // 注意上面要引入模組 "use strict"; module.show(); module.test(); </script>
引數相關
形參實參
形參是在函式宣告時設定的引數,實參指在呼叫函式時傳遞的值,注意,傳參時必須一一對應!
形引數量大於實參時,沒有傳參的形參值為
undefined
實引數量大於形參時,多於的實參將忽略並不會報錯
使用
函式名.length
可獲取需要傳遞形參的數量
<script> "use strict"; function test(f1, f2, f3) { console.log(f1); // 第一個 console.log(f2); // 第二個 console.log(f3); // undefined } test("第一個","第二個"); </script>
預設形參
預設形參要放在最後,當沒有實參傳遞時採用預設形參的值,當有實參傳遞時採用實參傳遞的值。
<script> "use strict"; function test(f1, f2, f3) { f3 = f3 || "預設形參"; // 老版設定預設形參的方式 console.log(f1); // 第一個 console.log(f2); // 第二個 console.log(f3); // 預設形參 } test("第一個","第二個"); </script>
<script> "use strict"; // 新版設定預設形參的方式 function test(f1, f2, f3="預設形參") { console.log(f1); // 第一個 console.log(f2); // 第二個 console.log(f3); // 預設形參 } test("第一個","第二個"); </script>
函式引數
函式本身也可當做一個引數傳遞給另一個函式。
<script> "use strict"; function f1(func) { console.log("f1..."); console.log("引數:",func); func("給f2傳遞的引數"); // 執行f2 } function f2(y) { console.log("f2"); console.log("引數:",y); } f1(f2); </script>
arguments
當某個函式要接收無限多的引數時,可不指定形參,使用arguments
來進行接收(必須是這個名字)。
注意:
arguments
是Arguments
物件,並不是一個陣列。但是我們可以將它轉換為陣列再進行操作
<script> "use strict"; function show() { console.log(arguments ); // Arguments(6) [1, 2, 3, 4, 5, 6, callee: (...), Symbol(Symbol.iterator): ƒ] } show(1,2,3,4,5,6); </script>
...語法
當形參要接收無限多的引數時,可在形參名前加入...
,使用進行接收。該形參會作為一個Array
物件接收無限多的引數。
這個是更推薦使用的方式
<script> "use strict"; function show(...args) { console.log(args ); // (6) [1, 2, 3, 4, 5, 6] } show(1,2,3,4,5,6); </script>
當實參是一個陣列或者類陣列的資料型別時,可以使用...
語法來為形參一一對應傳參。但是要注意,嚴格模式下不允許這樣做。
<script> // "use strict"; 嚴格模式下不能這麼做 function show(f1,f2,f3,f4,f5,f5) { console.log(f1); // 1 console.log(f2); // 2 console.log(f3); // 3 console.log(f4); // 4 console.log(f5); // 5 } show(...[1,2,3,4,5,6]); </script>
箭頭函式
箭頭函式是函式宣告的簡寫形式,在使用遞迴呼叫、建構函式、事件處理器時不建議使用箭頭函式。
無引數時使用空擴號即可,程式碼塊過於簡短可省略花括號。
函式體為單一表示式時不需要
return
返回處理,系統會自動返回表示式計算結果。多引數傳遞與普通宣告函式一樣使用逗號分隔
只有一個引數時可以省略引數括號。
無引數時使用空擴號即可,程式碼塊過於簡短可省略花括號。
<script> "use strict"; let show = () => console.log("執行了"); show(); </script>
函式體為單一表示式時不需要 return
返回處理,系統會自動返回表示式計算結果。
<script> "use strict"; let show = () => "你真帥"; const res = show(); console.log(res); // 你真帥 </script>
多引數傳遞與普通宣告函式一樣使用逗號分隔
<script> "use strict"; let show = (f1, f2, f3) => { console.log(f1); console.log(f2); console.log(f3); }; // 注意加分號 show("第一", "第二", "第三") </script>
只有一個引數時可以省略引數括號。
<script> "use strict"; let show = f1 => console.log(f1); show("第一") // 第一 </script>
遞迴呼叫
遞迴指函式內部呼叫自身的方式。
主要用於數量不確定的迴圈操作
要有退出時機否則會陷入死迴圈
以下示例將展示使用遞迴進行累加操作。
<script> "use strict"; function show(num) { if (!num) { return 0; } return num + show(num - 1); } let res = show(100); console.log(res); // 5050 </script>
以下示例將展示使用遞迴列印倒三角。
<script> "use strict"; function show(num) { if (!num) { return ; } console.log("*".repeat(num)); show(num - 1); } show(5); </script>
回撥函式
回撥函式是指在某一特定情況下會被其他函式所呼叫的函式,比如處理滑鼠事件,鍵盤事件的函式都是回撥函式。
<script> "use strict"; // 回撥函式 document.querySelector("div").addEventListener("click",(event)=> console.log(event.target)); // 由於this指向不同,所以我們使用event.target進行列印 </script>
標籤函式
當使用模板字面量對字串進行格式化時,可指定一個標籤函式。第一個引數是字串值的陣列,其餘的引數為標籤變數。
注意!標籤函式會自動執行!
<script> "use strict"; function show(str, ...args) { console.log(str); // (3) ["姓名是:", "↵年齡是:", "", raw: Array(3)] console.log(args); // (2) ["雲崖", 18] } let username = "雲崖"; let age = 18; let str = show`姓名是:${username}\n年齡是:${age}`; </script>