Es6-functions

提供:Dev Guides
移動先:案内検索

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

機能の分類

関数は、 Returning および Parameterized 関数に分類できます。

関数を返す

関数は、制御とともに値を呼び出し元に戻すこともできます。 このような関数は、戻り関数として呼び出されます。

以下は、返される関数の構文です。

function function_name() {
  //statements
   return value;
}
  • 戻り関数はreturnステートメントで終了する必要があります。
  • 関数は最大で1つの値を返すことができます。 つまり、関数ごとに1つのreturnステートメントのみが存在できます。
  • returnステートメントは、関数の最後のステートメントでなければなりません。

次のコードスニペットは、関数を返す例です-

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

上記の例では、文字列「hello world !!!」を呼び出し元に返す関数を定義しています。 上記のコードが正常に実行されると、次の出力が表示されます。

hello world!!!

パラメータ化された関数

パラメータは、値を関数に渡すメカニズムです。 パラメータは、関数の署名の一部を形成します。 パラメーター値は、呼び出し中に関数に渡されます。 明示的に指定されない限り、関数に渡される値の数は、定義されたパラメーターの数と一致する必要があります。

以下は、パラメーター化された関数を定義する構文です。

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

例-パラメータ化された関数

この例では、2つのパラメーター n1 および n2 を受け入れ、それらの合計を出力する関数addを定義しています。 パラメーター値は、呼び出されたときに関数に渡されます。

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では、値が渡されない場合、または定義されていない場合、関数を使用してパラメーターをデフォルト値で初期化できます。 同じことが次のコードに示されています。

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

次の例は、2つのパラメーターを取り、それらの合計を返す関数を示しています。 2番目のパラメーターのデフォルト値は10です。 つまり、2番目のパラメーターに値が渡されない場合、その値は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の変数引数に似ています。 残りのパラメーターは、関数に渡すことができる値の数を制限しません。 ただし、渡される値はすべて同じタイプでなければなりません。 つまり、残りのパラメーターは、同じ型の複数の引数のプレースホルダーとして機能します。

残りのパラメーターを宣言するために、パラメーター名の前に3つのピリオド(スプレッド演算子)が付けられます。 次の例は同じことを示しています。

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()コンストラクターが匿名関数を定義するために使用されます。 この関数は2つのパラメーターを受け入れ、その積を返します。

上記のコードが正常に実行されると、次の出力が表示されます。

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関数は、匿名関数を表す簡潔なメカニズムです。 これらの関数は、*矢印関数*とも呼ばれます。

ラムダ関数-解剖学

ラムダ関数には3つの部分があります-

  • パラメータ-関数はオプションでパラメータを持つことができます。
  • 太い矢印表記/ラムダ表記(⇒):行き先演算子としても呼ばれます。
  • ステートメント-関数の命令セットを表します。

ヒント-慣例により、コンパクトで正確な関数宣言のために、1文字のパラメーターの使用が推奨されます。

ラムダ式

これは、1行のコードを指す匿名関数式です。 以下は同じ構文です。

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

例-ラムダ式

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

例では、ラムダ式関数を宣言しています。 関数は、10と渡された引数の合計を返します。

上記のコードが正常に実行されると、次の出力が表示されます。

20

ラムダ声明

コードのブロックを指す匿名関数宣言です。 この構文は、関数の本体が複数行にわたる場合に使用されます。 以下は同じ構文です。

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

例-ラムダステートメント

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();

関数式と関数宣言

関数式と関数宣言は同義ではありません。 関数式とは異なり、関数宣言は関数名によってバインドされます。

2つの基本的な違いは、関数宣言が実行前に解析されることです。 一方、関数式は、実行中にスクリプトエンジンが検出した場合にのみ解析されます。

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)を使用して、ブロック内からの変数の巻き上げを回避できます。 関数内で定義された変数のプライバシーを保持しながら、メソッドへのパブリックアクセスを許可します。 このパターンは、自己実行の匿名関数と呼ばれます。 次の2つの例は、この概念をよりよく説明しています。

例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メソッドを呼び出すと実行されます。

ジェネレータは、機能キーワードの末尾にアスタリスクを付けることで示されます。それ以外の場合、それらの構文は通常の関数と同じです。

次の例は同じことを示しています。

"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が変数名に割り当てられ、「お好きなスポーツは何ですか?」が生成されます。再びジェネレーターが一時停止します。
  • 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 finddevguides is fun!!')
   },1000)
</script>

上記の例では、事前定義された* setTimeout()関数*にパラメーターとして無名関数を渡します。 setTimeout()関数は、1秒後に無名関数をコールバックします。

次の出力は、1秒後に表示されます-

Learning at finddevguides is fun!!

矢印関数の構文

ES6では、*無名関数*の使用を簡略化する*矢印関数*の概念が導入されています。 アロー関数には次の3つの部分があります-

  • パラメータ-矢印関数はオプションでパラメータを持つことができます
  • 太い矢印表記(⇒)-これは、gos to演算子としても呼び出されます
  • ステートメント-関数の命令セットを表します

ヒント-コンパクトで正確な矢印関数の宣言では、慣例により、1文字のパラメーターを使用することをお勧めします。

構文

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

OR

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

OR

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

例:ES6の矢印関数

次の例では、矢印関数を使用して2つの関数式 add および isEven を定義しています

<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 = ['finddevguides','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 :finddevguides
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()およびarrow関数

次の例では、矢印関数をパラメーターとして事前定義された* setTimeout()関数*に渡します。 * setTimeout()*関数は、1秒後に矢印関数をコールバックします。

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

次の出力は、1秒後に表示されます-

Learning at finddevguides is fun!!

アロー機能と「これ」

  • 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.firstName および this.lastName の値は undefined になります。 関数は、字句スコープまたは現在の実行のコンテキストを使用しません。 この問題は、*矢印関数*を使用して解決できます。

上記のコードの出力は次のようになります-

undefined undefined
Mohammad Mohtashim