6 函數 6.1 函數定義 函數可以封裝語句,然後在任何地方、任何時間執行。JavaScript中的函數使用function關鍵字聲明,主要由函數名、函數參數和函數體組成。其基本語法和聲明如下所示: 方式一: function functionName(arg0, arg1,...,argN) { ...
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,或掃描下麵的二維碼添加關註:
作者: Surpassme
來源: http://www.jianshu.com/u/28161b7c9995/
http://www.cnblogs.com/surpassme/
聲明:本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出 原文鏈接 ,否則保留追究法律責任的權利。如有問題,可發送郵件 聯繫。讓我們尊重原創者版權,共同營造良好的IT朋友圈。