二、(3)JavaScript函式
JavaScript-函式
1. 函式(重點)
函式:函式其實就是對一段程式碼進行封裝,被封裝的程式碼總是完成某項功能,函式不會主動的執行,需要在程式中手動的呼叫函式(比如:使用者點選的時候),並且可以多次呼叫這個函式。
函式的定義
因為函式可以封裝一個功能,該功能可以被多次使用從而達到程式碼重複使用,函式是程式碼封裝和程式碼複用的體現。
最簡單的定義語法
方式一:函式宣告,必須指定函式名
function 函式的名字(){ //功能程式碼(函式體) }
通過函式的名字呼叫執行,如果先多次執行,那麼就多次呼叫:
函式的名字();
方式二:函式表示式,函式名可以選
var 變數 = function(){ //功能程式碼(函式體) }; //函式其實也是一種資料型別,所有把函式賦值給一個變數是可行的,與var a =123與這種賦值一樣。
函式的呼叫
函式封裝(打包)了一段程式碼,被函式(打包)封裝的程式碼不會自動執行,它需要我們在合適的時候呼叫這個函式。
呼叫函式:其實就是執行函式中封裝的程式碼。
呼叫函式語法: 函式名();
函式定義舉例
函式引數(形式引數)
為什麼用形式引數(形參)
函式是用來完成一個功能,但是有時候後完成此功能時需要資料的參與,而這些資料只有在使用該功能時能夠確定。
呼叫函式時可以把函式中需要的資料傳入到函式中,那麼就需要使用引數。
比如:函式中,計算兩個數的和,但是這個兩個數可以是任何的資料。
形式引數定義
寫在函式定義中,出現在函式名的()裡面
function 函式名字(形式引數1,形式引數2){ 功能程式碼… }
1.2.3. 引數舉例說明
使用函式是傳入的引數資料叫做實際引數(實參)
執行過程: 實際引數分別賦值後形式引數後,方法才執行.
引數預設值
ES5:預設值方式
ES6:預設值方式
函式返回值
使用返回值:函式功能程式碼執行結果可能被其他的程式使用.
函式返回值定義
如果函式執行參結果的資料需要被其他程式所使用. 可以通過return關鍵字標記函式執行的結果(返回結果)。
function 函式名(形參1,形參2){ //功能程式碼. return 功能程式碼運算結果; }
返回值舉例
執行過程:將1賦值為num1, 2賦值給num2後在執行函式.
傳入實際引數時注意:
- 1. 實際引數列表的順序和形式引數的順序一一對應
- 2. 實際引數列表的型別和形式引數的期望型別一一對應
函式返回值注意點
① 函式第一次遇到return就結束執行,不管return後面還有多少程式碼都不執行
② 如果函式沒有指明return,函式預設的返回值為undefined,否則以return返回值為準
定義函式三部曲
function 函式名(引數,引數){ //功能程式碼 (函式體) return 返回值; } var result = 函式名(實參,實參);
練習:
1. 設計比較兩個數的最大值功能
2. 設計製作任意行數和列數表格的功能
<tr>
<td></td>
</tr>
2. 變數的作用域(重點)
變數作用域定義
變數作用域指的是一個變數在哪個範圍內可以使用,變數作用域被函式分為兩種。
- 全域性變數:函式外定義的變數,整個程式中都可以使用。
- 區域性變數:在某個特定的函式中定義的變數,稱之為區域性變數,只能夠在函式內部使用
全域性變數的特殊形式:在函式內定義但是沒有加var,也被作為全域性變數使用。
為什麼要用變數作用域
可以在不同的範圍內(函式外和函式內)使用相同的變數名字,引用不同的值。
如何選擇變數的作用域
如果變數的資料只在函式內部使用,請使用區域性變數。
如果變數的資料函式內部和外部都要使用,請使用全域性變數。
3. 編譯原理(瞭解)
一個奇怪的現象
JavaScript引擎執行原理(瞭解)
首先,在程式碼領域中,程式碼引擎是用來讀懂開發者編寫程式碼的一段程式。就如我們編寫了一段的JavaScript程式碼(var a = 1 +1),JavaScript引擎就是用來看懂(解析)這段JavaScript程式碼,計算獲得結果2,並將a的值變為2。
User.java ===> User.class(位元組碼) 編譯型語言(需要使用一個程式進行編譯,並生成另外一種可以被計算識別的語言.簡單理解,java這一類語言對計算機來說都是外語,需要翻譯)
User.js ==> User.js 解釋型語言(在執行時,才會進行編譯,進行解析和執行.直接可以識別,不需要翻譯)
語言主要分為兩大類:編譯型語言和解釋型語言。對於靜態語言來說(如Java、C++、C),處理上述這些事情的叫編譯器(Compiler),相應地對於JavaScript這樣的動態語言則叫直譯器(Interpreter)。這兩者的區別用一句話來概括就是:編譯器是將原始碼編譯為另外一種程式碼(比如機器碼,或者位元組碼),而直譯器是直接解析並將程式碼執行結果輸出。我們常用的firebug就是一個JavaScript直譯器。
當JavaScript引擎解析指令碼時,分為“語法分析”、“預編譯”和“解釋執行”三個階段。
- 1、“語法分析”階段。引擎檢查你的程式碼有沒有什麼低階的語法錯誤。
- 2、“預編譯”階段。首先會建立一個環境的上下文物件,然後把使用var宣告的變數,作為上下文物件的屬性,以undefined先行初始化;使用function關鍵字宣告的函式,也作為上下文物件的屬性,定義出來,而函式則保留了定義的內容。----在這個過程中,函式定義的優先順序 高於 變數定義。
- 3、“解釋執行”階段。遇到變數解析,會先在當前上下文物件中找,如果沒找到並且當前上下文物件有prototype屬性,則去原型鏈中找,否則將會去作用域鏈中找。
// 正確 alert(num); // 返回值undefined var num =100; alert(num); // 返回值100 // 正確 fn(); // 呼叫函式,返回值 ==> 函式呼叫成功!! function fn(){ alert(‘函式呼叫成功!!’); }
小結:
- 1. JavaScript引擎解析指令碼分為3個階段,預編譯和解釋執行
- 2. var變數和函式宣告都有提升,函式優先順序高
- 3. let&const沒有變數提升
4. 系統函式
定義:在瀏覽器已經定義好並且告知給計算機的函式(功能), 我們無需定義直接使用即可。
有哪些函式
- String(值):將值轉換為字串
- Number( 值):將值轉換為數字型別
- Boolean(值): 將非布林型別值轉為布林型別 0 “” null轉換為false 其餘轉換 為true
- parseInt (值):轉為整數
- parseFloat(值):轉為小數型別
- isNaN(值):判定 值 如果不是數字 返回為true 是數字返回為false
5. 遞迴函式(瞭解)
遞迴函式定義:在函式體內對函式自身呼叫。
案例:通過遞迴的函式打印出1—9的數值:
遞迴函式的前提
- 1. 完成使用者需要必須是一個函式
- 2. 函式必須有出口
為什麼要使用遞迴函式
大問題拆解成小問題,小問題與大問題的解決思路一致!它往往使函式的描述簡潔而且易於理解。
遞迴呼叫的特點
遞迴演算法所體現的“重複”一般有三個要求:
- 一是每次呼叫在規模上都有所縮小(通常是減半);
- 二是相鄰兩次重複之間有緊密的聯絡,前一次要為後一次做準備(通常前一次的輸出就作為後一次的輸入);
- 三是在問題的規模極小時必須用直接給出解答而不再進行遞迴呼叫,因而每次遞迴呼叫都是有條件的(以規模未達到直接解答的大小為條件),無條件遞迴呼叫將會成為死迴圈而不能正常結束。
例項:使用遞迴演算法列印1-num的累加
遞迴點: num+(num-1)
遞迴出口: num==1 || num==0;
/*使用遞迴演算法列印1-N的累加*/ function f(num){ if(num==1 || num==0){ return num; } return num+f(num-1); } console.log(f(100));
6. 作業
1、是否可以把函式賦值給一個變數,為什麼?
2、封裝函式,實現返回三個數的和
3、封裝函式,實現返回三個數的最小值
4、全域性變數和區域性變數的區別
5、使用遞迴求菲波拉契數列的第20個的值