ES6 - 函式



函式是可讀、可維護和可重用程式碼的構建塊。函式使用 function 關鍵字定義。以下是定義標準函式的語法。

function function_name() { 
   // function body 
} 

要強制執行函式,必須呼叫它。這稱為函式呼叫。以下是呼叫函式的語法。

function_name()

示例:簡單的函式定義

//define a  function 
function test() { 
   console.log("function called") 
} 
//call the function 
test()

此示例定義了一個函式 test()。一對定界符({ })定義函式體。它也稱為函式作用域。必須呼叫函式才能強制其執行。

在成功執行上述程式碼後,將顯示以下輸出。

function called

函式的分類

函式可以分為返回值引數化函式。

返回值函式

函式還可以將值與控制一起返回給呼叫方。此類函式稱為返回值函式。

以下是返回值函式的語法。

function function_name() { 
   //statements 
   return value; 
}
  • 返回值函式必須以 return 語句結尾。

  • 函式最多隻能返回一個值。換句話說,每個函式只能有一個 return 語句。

  • return 語句應該是函式中的最後一條語句。

以下程式碼片段是返回值函式的示例:

function retStr() { 
   return "hello world!!!" 
}  
var val = retStr() 
console.log(val) 

上面的示例定義了一個函式,該函式將字串“hello world!!!”返回給呼叫方。在成功執行上述程式碼後,將顯示以下輸出。

hello world!!! 

引數化函式

引數是將值傳遞給函式的一種機制。引數構成函式簽名的一部分。引數值在函式呼叫期間傳遞給函式。除非明確指定,否則傳遞給函式的值的數量必須與定義的引數數量匹配。

以下是定義引數化函式的語法。

function func_name( param1,param2 ,…..paramN) {   
   ...... 
   ...... 
}

示例 - 引數化函式

此示例定義了一個函式 add,該函式接受兩個引數n1n2並列印它們的和。引數值在呼叫函式時傳遞給函式。

function add( n1,n2) { 
   var sum = n1 + n2 
   console.log("The sum of the values entered "+sum) 
} 
add(12,13) 

在成功執行上述程式碼後,將顯示以下輸出。

The sum of the values entered 25

預設函式引數

在 ES6 中,如果函式沒有傳遞任何值或其值為 undefined,則函式允許將引數初始化為預設值。以下程式碼說明了這一點。

function add(a, b = 1) { 
   return a+b; 
} 
console.log(add(4))

上面的函式預設將 b 的值設定為 1。除非顯式傳遞了值,否則該函式將始終認為引數 b 具有值 1。在成功執行上述程式碼後,將顯示以下輸出。

5

如果函式顯式傳遞值,則將覆蓋引數的預設值。

function add(a, b = 1) { 
   return a + b; 
} 
console.log(add(4,2))

上面的程式碼將引數 b 的值顯式設定為 2,從而覆蓋其預設值。在成功執行上述程式碼後,將顯示以下輸出。

6

為了更好地理解,讓我們考慮以下示例。

示例 1

以下示例顯示了一個函式,該函式接受兩個引數並返回它們的和。第二個引數的預設值為 10。這意味著,如果未向第二個引數傳遞任何值,則其值為 10。

<script>
   function addTwoNumbers(first,second = 10){
      console.log('first parameter is :',first)
      console.log('second parameter is :',second)
      return first+second;
   }

   console.log("case 1 sum:",addTwoNumbers(20)) // no value
   console.log("case 2 sum:",addTwoNumbers(2,3))
   console.log("case 3 sum:",addTwoNumbers())
   console.log("case 4 sum",addTwoNumbers(1,null))//null passed
   console.log("case 5 sum",addTwoNumbers(3,undefined))
</script>

上述程式碼的輸出如下所示:

first parameter is : 20
second parameter is : 10
case 1 sum: 30
first parameter is : 2
second parameter is : 3
case 2 sum: 5
first parameter is : undefined
second parameter is : 10
case 3 sum: NaN
first parameter is : 1
second parameter is : null
case 4 sum 1
first parameter is : 3
second parameter is : 10
case 5 sum 13

示例 2

<script>
   let DEFAULT_VAL = 30
      function addTwoNumbers(first,second = DEFAULT_VAL){
         console.log('first parameter is :',first)
         console.log('second parameter is :',second)
         return first+second;
      }
      console.log("case 1 sum",addTwoNumbers(1))
      console.log("case 2 sum",addTwoNumbers(3,undefined))
</script>

上述程式碼的輸出如下所示:

first parameter is : 1
second parameter is : 30
case 1 sum 31
first parameter is : 3
second parameter is : 30
case 2 sum 33

剩餘引數

剩餘引數類似於 Java 中的可變引數。剩餘引數不限制您可以傳遞給函式的值的數量。但是,傳遞的值必須全部為同一型別。換句話說,剩餘引數充當同一型別多個引數的佔位符。

要宣告剩餘引數,引數名稱以三個點為字首,稱為擴充套件運算子。以下示例說明了這一點。

function fun1(...params) { 
   console.log(params.length); 
}  
fun1();  
fun1(5); 
fun1(5, 6, 7); 

在成功執行上述程式碼後,將顯示以下輸出。

0 
1 
3

注意 - 剩餘引數應位於函式引數列表的最後。

匿名函式

未繫結到識別符號(函式名稱)的函式稱為匿名函式。這些函式是在執行時動態宣告的。匿名函式可以接受輸入並返回輸出,就像標準函式一樣。匿名函式在其初始建立後通常無法訪問。

變數可以分配匿名函式。這樣的表示式稱為函式表示式

以下是匿名函式的語法。

var res = function( [arguments] ) { ... } 

示例 - 匿名函式

var f = function(){ return "hello"} 
console.log(f()) 

在成功執行上述程式碼後,將顯示以下輸出。

hello 

示例 - 匿名引數化函式

var func = function(x,y){ return x*y }; 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result) 
} 
product()

在成功執行上述程式碼後,將顯示以下輸出。

The product : 200 

函式建構函式

函式語句不是定義新函式的唯一方法;您可以使用 Function() 建構函式以及 new 運算子動態定義函式。

以下是使用 Function() 建構函式以及 new 運算子建立函式的語法。

var variablename = new Function(Arg1, Arg2..., "Function Body"); 

Function() 建構函式期望任意數量的字串引數。最後一個引數是函式體 - 它可以包含任意 JavaScript 語句,這些語句之間用分號隔開。

Function() 建構函式不會傳遞任何指定其建立的函式名稱的引數。

示例 - 函式建構函式

var func = new Function("x", "y", "return x*y;"); 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result)
} 
product()

在上面的示例中,Function() 建構函式用於定義一個匿名函式。該函式接受兩個引數並返回它們的乘積。

在成功執行上述程式碼後,將顯示以下輸出。

The product : 200

遞迴和 JavaScript 函式

遞迴是一種透過讓函式重複呼叫自身直到得到結果來迭代操作的技術。當您需要在迴圈中使用不同的引數重複呼叫同一個函式時,最適合使用遞迴。

示例 - 遞迴

function factorial(num) { 
   if(num <= 0) { 
      return 1; 
   } else { 
      return (num * factorial(num-1)  ) 
   } 
} 
console.log(factorial(6)) 

在上面的示例中,函式呼叫自身。在成功執行上述程式碼後,將顯示以下輸出。

720 

示例 - 匿名遞迴函式

(function() { 
   var msg = "Hello World" 
   console.log(msg)
})()

該函式使用一對括號()呼叫自身。在成功執行上述程式碼後,將顯示以下輸出。

Hello World 

Lambda 函式

Lambda 指的是程式設計中的匿名函式。Lambda 函式是一種簡潔的表示匿名函式的機制。這些函式也稱為箭頭函式

Lambda 函式 - 結構

Lambda 函式有 3 個部分:

  • 引數 - 函式可以選擇具有引數。

  • 胖箭頭表示法/lambda 表示法(=>):它也稱為轉到運算子。

  • 語句 - 表示函式的指令集。

提示 - 根據慣例,鼓勵對緊湊而精確的函式宣告使用單個字母引數。

Lambda 表示式

它是一個指向單行程式碼的匿名函式表示式。以下是相同的語法。

([param1, parma2,…param n] )=>statement;

示例 - Lambda 表示式

var foo = (x)=>10+x 
console.log(foo(10)) 

此示例聲明瞭一個 lambda 表示式函式。該函式返回 10 與傳遞的引數的和。

在成功執行上述程式碼後,將顯示以下輸出。

20

Lambda 語句

它是一個指向程式碼塊的匿名函式宣告。當函式體跨越多行時,使用此語法。以下是相同的語法。

( [param1, parma2,…param n] )=> {       
   //code block 
}

示例 - Lambda 語句

var msg = ()=> { 
   console.log("function invoked") 
} 
msg() 

函式的引用被返回並存儲在變數 msg 中。在成功執行上述程式碼後,將顯示以下輸出。

function  invoked 

語法變體

單個引數的可選括號。

var msg = x=> { 
   console.log(x) 
} 
msg(10)

單個語句的可選大括號。無引數的空括號。

var disp = ()=>console.log("Hello World") 
disp();

函式表示式和函式宣告

函式表示式和函式宣告不是同義詞。與函式表示式不同,函式宣告受函式名稱約束。

兩者之間的根本區別在於,函式宣告在執行之前進行解析。另一方面,函式表示式僅在指令碼引擎在執行過程中遇到它時才進行解析。

當 JavaScript 解析器在主程式碼流中看到一個函式時,它會假設函式宣告。當函式作為語句的一部分出現時,它就是一個函式表示式。

函式提升

像變數一樣,函式也可以提升。與變數不同,函式宣告在提升時會提升函式定義,而不僅僅是提升函式名稱。

以下程式碼片段說明了 JavaScript 中的函式提升。

hoist_function();  
function hoist_function() { 
   console.log("foo"); 
} 

在成功執行上述程式碼後,將顯示以下輸出。

foo 

但是,函式表示式不能提升。以下程式碼片段說明了這一點。

hoist_function(); // TypeError: hoist_function() is not a function  
var hoist_function() = function() { 
   console.log("bar"); 
};

立即呼叫函式表示式

立即呼叫函式表示式 (IIFE) 可用於避免塊內的變數提升。它允許公開訪問方法,同時保留函式內定義的變數的私密性。這種模式稱為自執行匿名函式。以下兩個示例更好地解釋了這個概念。

示例 1:IIFE

var main = function() { 
   var loop = function() { 
      for(var x = 0;x<5;x++) {
         console.log(x); 
      } 
   }(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

示例 2:IIFE

var main = function() { 
   (function() { 
      for(var x = 0;x<5;x++) { 
         console.log(x); 
      } 
   })(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

這兩個示例都將呈現以下輸出。

0 
1 
2 
3 
4 
Uncaught ReferenceError: x is not define

生成器函式

當呼叫普通函式時,控制權保留在被呼叫的函式中,直到它返回。使用 ES6 中的生成器,呼叫函式現在可以控制被呼叫函式的執行。生成器類似於常規函式,除了:

  • 函式可以在任何時候將控制權返回給呼叫方。

  • 當您呼叫生成器時,它不會立即執行。相反,您會得到一個迭代器。當您呼叫迭代器的 next 方法時,函式就會執行。

生成器用在 function 關鍵字後面加上星號來表示;否則,它們的語法與常規函式相同。

以下示例說明了這一點。

"use strict" 
function* rainbow() { 
   // the asterisk marks this as a generator 
   yield 'red'; 
   yield 'orange'; 
   yield 'yellow'; 
   yield 'green'; 
   yield 'blue'; 
   yield 'indigo'; 
   yield 'violet'; 
} 
for(let color of rainbow()) { 
   console.log(color); 
} 

生成器允許呼叫方和被呼叫函式之間進行雙向通訊。這是透過使用yield關鍵字來實現的。

考慮以下示例:

function* ask() { 
   const name = yield "What is your name?"; 
   const sport = yield "What is your favorite sport?"; 
   return `${name}'s favorite sport is ${sport}`; 
}  
const it = ask(); 
console.log(it.next()); 
console.log(it.next('Ethan'));  
console.log(it.next('Cricket')); 

生成器函式的順序如下:

  • 生成器以暫停狀態啟動;返回迭代器。

  • it.next() 生成“你的名字是什麼”。生成器已暫停。這是由 yield 關鍵字完成的。

  • 呼叫 it.next(“Ethan”) 將值 Ethan 分配給變數 name 並生成“你最喜歡的運動是什麼?”生成器再次暫停。

  • 呼叫 it.next(“Cricket”) 將值 Cricket 分配給變數 sport 並執行後續的 return 語句。

因此,上述程式碼的輸出將是:

{ 
   value: 'What is your name?', done: false 
} 
{ 
   value: 'What is your favorite sport?', done: false 
} 
{ 
   value: 'Ethan\'s favorite sport is Cricket', done: true 
}

注意 - 生成器函式不能使用箭頭函式表示。

箭頭函式

ES 中引入的箭頭函式有助於以簡潔的方式編寫 JavaScript 中的函式。現在讓我們詳細瞭解一下。

ES5 和匿名函式

JavaScript 廣泛使用匿名函式。匿名函式是指沒有與之關聯名稱的函式。匿名函式用於函式回撥。以下示例說明了在 ES5 中使用匿名函式:

<script>
   setTimeout(function(){
      console.log('Learning at TutorialsPoint is fun!!')
   },1000)
</script>

以上示例將一個匿名函式作為引數傳遞給預定義的setTimeout() 函式。setTimeout() 函式將在 1 秒後回撥匿名函式。

1 秒後顯示以下輸出:

Learning at TutorialsPoint is fun!!

箭頭函式語法

ES6 引入了箭頭函式的概念,以簡化匿名函式的使用。箭頭函式包含三個部分,如下所示:

  • 引數 - 箭頭函式可以選擇性地包含引數

  • 胖箭頭符號 (=>) - 也稱為“轉到”運算子

  • 語句 - 表示函式的指令集

提示 - 根據約定,建議對於簡潔且精確的箭頭函式宣告使用單個字母引數。

語法

//Arrow function that points to a single line of code
()=>some_expression

//Arrow function that points to a block of code
()=> { //some statements }`

//Arrow function with parameters
(param1,param2)=>{//some statement}

示例:ES6 中的箭頭函式

以下示例使用箭頭函式定義了兩個函式表示式addisEven

<script>
   const add = (n1,n2) => n1+n2
   console.log(add(10,20))

   const isEven = (n1) => {
      if(n1%2 == 0)
         return true;
      else
         return false;
   }
   console.log(isEven(10))
</script>

上述程式碼的輸出如下所示:

30
true

Array.prototype.map() 和箭頭函式

在以下示例中,一個箭頭函式作為引數傳遞給Array.prototype.map() 函式。map() 函式對陣列中的每個元素執行箭頭函式。在這種情況下,箭頭函式顯示陣列中的每個元素及其索引。

<script>
   const names = ['TutorialsPoint','Mohtashim','Bhargavi','Raja']
   names.map((element,index)=> {
      console.log('inside arrow function')
      console.log('index is '+index+' element value is :'+element)
   })
</script>

以上程式碼的輸出將如下所示:

inside arrow function
index is 0 element value is :TutorialsPoint
inside arrow function
index is 1 element value is :Mohtashim
inside arrow function
index is 2 element value is :Bhargavi
inside arrow function
index is 3 element value is :Raja

示例:window.setTimeout() 和箭頭函式

以下示例將一個箭頭函式作為引數傳遞給預定義的setTimeout() 函式setTimeout() 函式將在 1 秒後回撥箭頭函式。

<script>
   setTimeout(()=>{
      console.log('Learning at TutorialsPoint is fun!!')
   },1000)
</script>

1 秒後顯示以下輸出:

Learning at TutorialsPoint is fun!!

箭頭函式和“this”

在箭頭函式內部,如果我們使用this 指標,它將指向封閉的詞法作用域。這意味著箭頭函式不會在每次呼叫時建立一個新的this 指標例項。箭頭函式使用其封閉的作用域。為了理解這一點,讓我們看一個例子。

<script>
   //constructor function
   function Student(rollno,firstName,lastName) {
      this.rollno = rollno;
      this.firstName = firstName;
      this.lastName = lastName;
      this.fullNameUsingAnonymous = function(){
         setTimeout(function(){
            //creates a new instance of this ,hides outer scope of this
            console.log(this.firstName+ " "+this.lastName)
         },2000)
      }
      this.fullNameUsingArrow = function(){
         setTimeout(()=>{
            //uses this instance of outer scope
            console.log(this.firstName+ " "+this.lastName)
         },3000)
      }
   }
   const s1 = new Student(101,'Mohammad','Mohtashim')
   s1.fullNameUsingAnonymous();
   s1.fullNameUsingArrow();
</script>

當匿名函式與setTimeout()一起使用時,函式將在 2000 毫秒後被呼叫。會建立一個新的“this”例項,它會覆蓋 Student 函式的例項。因此,this.firstNamethis.lastName 的值將為undefined。該函式不使用詞法作用域或當前執行的上下文。這個問題可以透過使用箭頭函式來解決。

以上程式碼的輸出將如下所示:

undefined undefined
Mohammad Mohtashim
廣告