1. 程式人生 > 實用技巧 >二、(3)JavaScript函式

二、(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個的值