JS函數

本質

  函數用來封裝須要屢次使用的代碼塊數組

  函數也是一個對象,所以能夠給函數添加屬性方法,並做爲數據值(利用函數的返回值)/參數(特定函數如setTimeout)/返回值使用app

  把函數當參數傳遞時,函數名即爲函數本體裏面的代碼塊),無需添加括號(添加括號即爲執行函數ide

  

  當函數做爲返回值時,爲了調用返回的函數,須要在函數本體(函數名)後加()來執行函數

  

 

組成

  函數包括函數名形式參數實際參數、返回值this

  函數名是指向函數在內存中位置的介質,可省略(此時叫匿名函數)spa

  

  定義函數時函數名後的括號裏即爲形式參數(形參),不是必填,且形參和實參的數目沒必要相等code

  使用函數時實際傳入的參數爲實際參數(實參)對象

  函數內部return後的語句即返回值blog

 

意義

  函數使得代碼得以複用(不須要屢次Ctrl+C、Ctrl+V複製粘貼,只要調用函數便可使用相同的代碼塊執行特定功能)遞歸

  便於代碼的維護和修改(只需在函數中修改代碼便可,調用函數的地方隨之修改)

  增長程序的可讀性(把實現方法的細節封裝在函數中,用函數名來表示實現的方法,更易理解)

 

定義方法

字面量

  包括function聲明var賦值表達式

1 function add(){
2     console.log('I like swimming');
3 }
1 var add = function(){
2     console.log('I like swimming');
3 }

  function聲明函數會預解析,執行函數放在函數定義前也能夠順利執行(聲明提早

  var賦值表達式定義函數,在預解析時會將變量賦值爲undefined,若是執行函數的操做在定義函數前,則報錯

構造函數

  構建一個function對象的實例,其中形參和代碼塊都放在引號中

var add = new Function('num1','num2','return num1+num2;');

 

定義位置

  函數可定義在全局環境局部環境(函數/對象內部)中

  在全局中定義的函數,在全局內部任意位置均可以找到並調用這個函數

  在局部中定義的函數,只可經過做用域鏈,向上一層找到該函數,若是找不到則報錯

 

調用

直接調用

1.匿名函數

  1.將其賦值給一個變量,用變量名()來實現調用

1 var add = function(){
2     alert(1);
3 }
4 add();
unnamed function

  2.直接用函數本體後加()的形式自我執行

  這裏的原理是:用function聲明的函數會被識別並預解析,而在function前加合法的符號(+-!~等),不讓函數以function打頭,則函數不會被預解析,從而實現自執行

  所以,在執行的()外/內加一組括號都是能夠的

1 !+-~function(){
2     alert(1);
3 }();
unnamed function2
1 (function (){
2     alert(1);
3 })();
unnamed function3

  可是要注意,自執行的函數也是有做用域的,執行完畢後,內部的做用域被銷燬

  

2.遞歸調用

  在函數內部調用自身

  注意調用次數不要超過最大的遞歸層數

1 function factorial(num){
2     if(num == 1){
3         return 1;
4     }
5     else{
6         return num*factorial(num-1);
7     }
8 }
9 console.log(factorial(5));

3.方法調用

  不合法的方法名(屬性名)須要用引號括起來(例如@),調用時用[](例如add['@'](1,2))

  若是調用的方法名是一個字符串,則也使用[]

  

  方法也能夠鏈式調用,但該對象裏的每一個方法須要返回當前對象(不然會形成undefined.方法的結果,出現報錯)

  不推薦過分使用鏈式調用

 1 var operation = {
 2     add:function(num1,num2){
 3         console.log(+num1+ +num2);
 4         return this;
 5     },
 6     subtract:function(num1,num2){
 7         console.log(num1-num2);
 8         return this;
 9     }
10 }
11 operation.add(1,2).subtract(3,2);

 4.構造函數調用

  經過new 構造函數名()來調用(例如new Object())

  調用完成後返回一個對象(該構造函數實例化的對象)

 

間接調用

  即不使用函數中的方法名()來調用方法,而是用函數名.方法名.apply()/call()來間接調用方法

  注意此處函數名後不可跟()

  

  call和apply方法的第一個參數都是用來改變方法中this的指向的,第二個參數apply可接收一個數組,把數組中每一個元素做爲參數傳入,而call只可接收一個個獨立的參數

   

 

參數

類型

  形式參數(形參):聲明函數時的‘佔位用’參數(在預解析時被當作函數的局部變量),可用函數名.length屬性來訪問到其個數

  實際參數(實參):調用函數時傳入的參數,可用arguments.length屬性訪問其個數

  參數傳遞的本質:實參賦值給形參

個數

  1.實參數目=形參數目:按照定義函數時的順序,把實參一一賦值給形參

  2.實參數目<形參數目:未被賦值的形參爲undefined

    通常會在有可選參數時使用(若是不傳遞某個參數,給這個參數默認值)

1 function power(base,power){
2     if(!power){
3         power = 2;
4     }
5     return Math.pow(base,power);
6 }
7 console.log(power(3));//返回的是9

  3.實參數目>形參數目:多餘的實參不被歸入函數的調用範圍,會正常運行

參數的類數組對象arguments

  arguments裏保留了全部的實參(以鍵值對形式存儲)、length屬性、callee方法

  建議不要在函數中對arguments對象進行修改操做

  callee方法能夠返回arguments對象的函數,防止函數名變化時,內部遞歸調用的函數名稱也須要同時改變(嚴格模式下callee方法不可用

1 function jiecheng(num){
2     if(num == 1){
3         return 1;
4     }
5     else{
6         return num*arguments.callee(num-1);
7     }
8 }
9 console.log(jiecheng(5));

   嚴格模式下,能夠把命名函數賦值給經過var聲明的變量,來達到相似callee的效果(變量名變化時,函數名以及函數內部自調用的名稱不要變,只要改變變量名

1 var jiecheng = function f1(num){
2     if(num == 1){
3         return 1;
4     }
5     else{
6         return num*f1(num-1);
7     }
8 }
9 console.log(jiecheng(5));

 可當參數的東西

  1.參數能夠爲空(聲明函數時,括號中能夠爲空)

  2.能夠經過做用域鏈,用上一級的局部變量/全局變量來做爲函數的參數

  3.能夠傳遞基本類型數據(數字、字符串、布爾值、undefined、null)或引用類型數據(數組、對象(參數三個以上時推薦使用)、函數)

     其中傳入對象能夠解決了參數傳遞時必須按照形參順序的問題

  

 

返回值

含義

  函數結束,將後續的內容返回(不然返回undefined)

可當返回值的東西

  1.返回值能夠爲空,即函數到此終止,返回undefined

  2.返回值可爲基本類型數據(數字、字符串(alert函數)、布爾值、undefined、null)、引用數據類型(數組、對象、函數)

  

  document.write()方法指望返回的是字符串,若是不是,會調用toString方法將其返回爲字符串

  

相關文章
相關標籤/搜索