JavaScript快速入門-06-函數

6 函數

6.1 函數定義

    函數可以封裝語句,然後在任何地方、任何時間執行。JavaScript中的函數使用function關鍵字聲明,主要由函數名函數參數函數體組成。其基本語法和聲明如下所示:

  • 方式一:
function functionName(arg0, arg1,...,argN) {
	statements
}
  • 方式二:
let variable=function(arg0, arg1,...,argN) {
	statements
}
  • 方式三:
let variable=(arg0, arg1,...,argN) => {
	statements
}
  • 如果函數無返回值,則不需要return語句,如果有返回值,則需要return語句
  • 在碰到return語句後,則立即返回,後續語句不再執行

    示例如下所示:

// 無返回值函數
function hello(name){
    console.log("Hello ,",name);
}
// 存在返回值函數
function sum(number1,number2){
    return number1+number2;
}

// 遇到return語句,提前返回
function testReturn(age){
   return "test return ";
   console.log("age is:",age);

}

// 使用函數表達式定義函數
let diff=function(number1,number2){
    return number1-number2
}

// 箭頭函數
let mul=(number1,number2) =>{
    return number1*number2;
}

hello("Surpass");
console.log("sum is :",sum(7,18));
console.log(testReturn(18));
console.log("diff is:",diff(7,18));
console.log("mul is:",mul(7,18));

輸出結果如下所示:

Hello , Surpass
sum is : 25
test return
diff is: -11
mul is: 126

6.2 箭頭函數

    箭頭函數實例化的函數對象與正式的函數表達式創建的函數對象行爲是相同的。任何可以使用函數表達式的地方,都可以使用箭頭函數。需要注意事項如下所示:

  • 1、在僅有一個參數時,可以省略括號,以下兩種寫法完全等效:
let absValue1=(x)=>{return Math.abs(x);};
let absValue2=x=>{return Math.abs(x);};
  • 2、當沒有參數時,括號不能省略
let getRandomNumber=()=>{return Math.random()*10;};
  • 3、多個參數也需要括號
let div=(a,b)=>{
    if(b!=0){
        return a/b;
    }
    else{
        return Infinity;
    }
};
  • 4、大括號省略注意事項:

箭頭函數也可以不使用大括號,但這樣會改變函數的行爲。使用大括號就說明包含函數體,即可以在一個函數中包含多條語句,跟常規函數一樣。如果不使用大括號,則箭頭後面就只能有一行代碼,如一個表達式、賦值操作等。而且,省略大括號會隱式返回這行代碼的值。

    示例代碼如下所示:

// 以下兩種寫法都有效
let power1=(x)=>{return x**2;};
let power2=x=>x**2;

console.log("power1 is:"+power1(2)+"\npower2 is:"+power2(2));

// 進行賦值操作
let personInfo={};
let setPersonInfoName=(name)=>personInfo.name=name;
setPersonInfoName("Surpass");
console.log("personInfo is:",personInfo);

// 無效寫法
let sum=(number1,number2)=> return number1+number2;

    箭頭函數雖然語法簡潔,但也有很多場合不適用。箭頭函數不能使用arguments、super 和new.target,也不能用作構造函數。此外,箭頭函數也沒有prototype屬性

6.3 函數名

    因爲函數名就是指向函數的指針,所以它們跟其他包含對象指針的變量具有相同的行爲。即一個函數可以有多個名稱,如下所示:

function sum(number1,number2){
    return number1+number2;
}

console.log("Sum is: ",sum(10,18)); // 28

let refSum=sum;
console.log("refSum is: ",refSum(10,18)); // 28

sum=null;
console.log("refSum is: ",refSum(10,18)); // 28

    以上代碼定義了sum()的函數,並將sum賦值給refSum,使用不帶括號的函數名會訪問函數指針,並不會執行函數。此時,refSum和sum都指向同一個函數。調用refSum()也可以返回結果。再將sum賦爲null之後,就切斷了它與函數之間的關聯,所以refSum()依然可以照常調用。

6.4 函數參數

    在JavaScript中,函數不關心傳入的參數個數數據類型。其函數參數,在內部表現一個數組,因此函數調用時都會接收到一個數組,函數並不關心數組中包含什麼。

1.定義函數時,聲明有兩個參數,在調用時並不一定就需要傳入兩個參數,也可以傳一個,兩個,三個或不傳,解釋器也並不會報錯。
2.在使用function關鍵字定義(非箭頭)函數,可以在函數內部訪問arguments對象,從中獲取傳入的每個參數值

// 使用參數一
function hello_1(name,message){
    console.log("call function ",hello_1.name);
    return "Hello"+name+message;
}
// 使用參數二:arguments
function hello_2(){
    console.log("call function ",hello_2.name);
    console.log("input para length is:",arguments.length);
    return "Hello"+arguments[0]+arguments[1];
}

console.log(hello_1(" Surpass"," Welcome to Shanghai"));
console.log(hello_2(" Surpass"," Welcome to Shanghai"));

輸出結果如下所示:

call function  hello_1
Hello Surpass Welcome to Shanghai
call function  hello_2
input para length is: 2
Hello Surpass Welcome to Shanghai

    在函數中,arguments對象可以跟參數一起使用,如下所示:

function add(number1,number2){
   let paraLength=arguments.length;
   if (paraLength == 1){
       return number1;
   } else if (paraLength ==2 ){
      return arguments[0]+number2;
   } else {
       let sum=0;
       for(let item of arguments){
          sum+=item;
       }
       return sum;
   }
}

console.log("result is:",add(1));
console.log("result is:",add(1,2));
console.log("result is:",add(1,2,3));

輸出結果如下所示:

result is: 1
result is: 3
result is: 6

如果函數是箭頭函數,則傳入的參數不能再使用arguments關鍵字訪問,而只能通過定義的參數名稱來訪問

6.5 沒有重載

    JavaScript不像Java/C#等,存在函數重載功能。因爲在JavaScript中函數不一定有函數名稱,參數可以是0個或多個,所以自然就沒有重載功能。如果在JavaScript中定義了兩個同名函數,則後面定義的函數會覆蓋前面定義的函數。示例如下所示:

function sum(){
    return arguments[0]+28;
}

function sum(){
    return arguments[0]+128;
}

let result=sum(100);
console.log("result is:",result) // 228

6.6 參數默認值

    在ECMAScript5.1 及以前,默認參數值爲undefined,而在ECMAScript 6 之後,則可以支持顯式定義默認參數了,如下所示:

  • 1.給參數傳undefined 相當於沒有傳值,好處是可以利用多個獨立的默認值
function hello(name="Surpass",message=" Welcome"){
    return `Hello  ${name} ${message}`;
}

console.log(hello()); // Hello Surpass  Welcome
console.log(hello("Kevin","Welcome to Shanghai")); // Hello Kevin Welcome to Shanghai
console.log(hello(undefined,"Welcome to Shanghai")); // Hello Surpass Welcome to Shanghai
  • 2.在使用默認參數時,arguments 對象的值不反映參數的默認值,只反映傳給函數的參數,,修改命名參數也不會影響arguments 對象,它始終以調用函數時傳入的值爲準
function hello(name="Surpass",message=" Welcome"){
    name="Kevin";
    return `Hello  ${arguments[0]} ${message}`;
}

console.log(hello()); // Hello  undefined  Welcome
console.log(hello("Kevin","Welcome to Shanghai")); // Hello Kevin Welcome to Shanghai
  • 3.默認參數值並不限於原始值或對象類型,也可以使用調用函數返回的值
let name=["Surpass","Kevin","Tina","Jeniffer"];
let city=["Shanghai","Wuhan","Nanjing","Suzhou"];
let nameIndex=0,cityIndex=0;

function getCity(){
    // 每次調用後遞增
    return city[cityIndex++];
}

function getName(){
  return name[nameIndex++];
}

function hello(name=getName(),message=getCity()){
   return `Hello ${name},Welcome ${message}`;
}

for (let i = 0; i < city.length; i++) {
    console.log(hello());
}

輸出結果如下所示:

Hello Surpass,Welcome Shanghai
Hello Kevin,Welcome Wuhan
Hello Tina,Welcome Nanjing
Hello Jeniffer,Welcome Suzhou

函數的默認參數只有在函數被調用時纔會求值,不會在函數定義時求值

  • 4.箭頭函數同樣也可以使用默認參數,但在僅有一個參數時,則不能省略括號
let hello=(name="Surpass")=>{return `Hello ${name}`;}

console.log(hello()); // Hello Surpass 
console.log(hello("Kevin")); // Hello Kevin

6.7 參數擴展和收集

    ECMAScript 6 新增了擴展操作符,使用它可以非常簡潔地操作和組合集合數據。擴展操作符最有用的場景就是函數定義中的參數列表。既可以用於調用函數時傳參,也可以用於定義函數參數。

6.7.1 擴展參數

    先來看看示例代碼,如下所示:

function sum(){
    let sum=0;
    for (let index = 0; index < arguments.length; index++) {
        sum+=arguments[index];
    }
    return sum;
}
let number=[1,2,3,4,5];
console.log("sum is :",sum(number)); // sum is : 01,2,3,4,5

    以上函數功能是希望將傳入的參數進行累加處理。如果不使用擴展操作符,則需要在傳入函數前,將參數進行拆分處理,可以使用apply()方法

console.log("sum is :",sum.apply(null,number)); // sum is : 15

    在ECMAScript 6 中,可以通過擴展操作符實現這種操作。對可迭代對象應用擴展操作符,並將其作爲一個參數傳入,可將可迭代對象拆分,並將迭代返回的每個值單獨傳入。示例如下所示:

function sum(){
    let sum=0;
    for (let index = 0; index < arguments.length; index++) {
        sum+=arguments[index];
    }
    return sum;
}

let number=[1,2,3,4,5];
// 使用擴展操作符
console.log("sum is :",sum(...number));  // sum is : 15

    因爲數組的長度已知,所以在使用擴展操作符傳參的時候,並不妨礙在其前面或後面再傳其他的值,包括使用擴展操作符傳其他參數,示例如下所示:

console.log("sum is :",sum(-10,...number)); // sum is : 5
console.log("sum is :",sum(-10,...number,95)); // sum is : 100
console.log("sum is :",sum(-10,...number,...[1,2,3,4],10)); // sum is : 25

擴展參數操作符其主要作用是將傳入的參數進行拆分爲單個元素。

6.7.2 收集參數

    先來看看示例代碼,如下所示:

function getArray(...numbers){
    return numbers;
}

console.log(getArray(1,2,3)) // [ 1, 2, 3 ]

在定義函數時,可以使用擴展操作符把不同長度的獨立參數組合爲一個數組(類似arguments對象的構造機制,收集參數的結果會得到一個數組實例),

    在使用收集參數操作符,注意事項如下所示:

  • 收集參數只能位於命名參數之後(因爲收集參數的結果可變,因此僅能做爲最後一個參數)
  • 收集參數前面如果有命令參數,則僅會收集其餘的參數
  • 箭頭函數支持收集參數操作符
// 不可以這樣定義
function getArrayA(...value,lastPara){}

// 必須要這樣聲明
function getArrayB(firstPara,...numbers){
    return numbers;
}
// 箭頭函數支持收集參數
let getArrayC=(...values) =>{return values;};

console.log(getArrayB()) // []
console.log(getArrayB(1,2,3)) // [ 2, 3 ]
console.log(getArrayB(1,2,3,4,5,6)) // [2, 3, 4, 5, 6]
console.log(getArrayC(1,2,3,4,5,6)) // [1, 2, 3, 4, 5, 6]

原文地址:https://www.jianshu.com/p/07328d8a31f7

本文同步在微信訂閱號上發佈,如各位小夥伴們喜歡我的文章,也可以關注我的微信訂閱號:woaitest,或掃描下面的二維碼添加關注:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章