ES6 - Funções

Functionssão os blocos de construção de código legível, sustentável e reutilizável. As funções são definidas usando a palavra-chave function. A seguir está a sintaxe para definir uma função padrão.

function function_name() { 
   // function body 
}

Para forçar a execução da função, ela deve ser chamada. Isso é chamado de invocação de função. A seguir está a sintaxe para invocar uma função.

function_name()

Exemplo: definição de função simples

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

O exemplo define uma função test (). Um par de delimitadores ({}) define o corpo da função. Também é chamado defunction scope. Uma função deve ser chamada para forçar sua execução.

A seguinte saída é exibida na execução bem-sucedida do código acima.

function called

Classificação de funções

As funções podem ser classificadas como Returning e Parameterized funções.

Funções de retorno

As funções também podem retornar o valor junto com o controle, de volta para o chamador. Essas funções são chamadas de funções de retorno.

A seguir está a sintaxe da função de retorno.

function function_name() { 
   //statements 
   return value; 
}
  • Uma função de retorno deve terminar com uma instrução de retorno.

  • Uma função pode retornar no máximo um valor. Em outras palavras, pode haver apenas uma instrução de retorno por função.

  • A instrução de retorno deve ser a última instrução da função.

O seguinte snippet de código é um exemplo de função de retorno -

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

O exemplo acima define uma função que retorna a string “hello world !!!” para o chamador. A seguinte saída é exibida na execução bem-sucedida do código acima.

hello world!!!

Funções parametrizadas

Os parâmetros são um mecanismo para passar valores para funções. Os parâmetros fazem parte da assinatura da função. Os valores dos parâmetros são passados ​​para a função durante sua invocação. A menos que seja especificado explicitamente, o número de valores passados ​​para uma função deve corresponder ao número de parâmetros definidos.

A seguir está a sintaxe que define uma função parametrizada.

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

Example − Parameterized Function

O exemplo define uma função add que aceita dois parâmetros n1 e n2e imprime sua soma. Os valores dos parâmetros são passados ​​para a função quando ela é chamada.

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

A seguinte saída é exibida na execução bem-sucedida do código acima.

The sum of the values entered 25

Parâmetros de função padrão

No ES6, uma função permite que os parâmetros sejam inicializados com valores padrão, se nenhum valor for passado para ela ou se ela for indefinida. O mesmo é ilustrado no código a seguir.

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

A função acima define o valor de b como 1 por padrão. A função sempre considerará o parâmetro b como tendo o valor 1, a menos que um valor tenha sido passado explicitamente. A seguinte saída é exibida na execução bem-sucedida do código acima.

5

O valor padrão do parâmetro será sobrescrito se a função passar um valor explicitamente.

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

O código acima define o valor do parâmetro b explicitamente como 2, substituindo assim seu valor padrão. A seguinte saída é exibida na execução bem-sucedida do código acima.

6

Para melhor compreensão, consideremos o exemplo abaixo.

Exemplo 1

O exemplo a seguir mostra uma função que recebe dois parâmetros e retorna sua soma. O segundo parâmetro tem um valor padrão de 10. Isso significa que, se nenhum valor for passado para o segundo parâmetro, seu valor será 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>

A saída do código acima será conforme mencionado abaixo -

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

Exemplo 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>

A saída do código acima será conforme mostrado abaixo -

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

Parâmetros de repouso

Os parâmetros de descanso são semelhantes aos argumentos variáveis ​​em Java. Os parâmetros de descanso não restringem o número de valores que você pode passar para uma função. No entanto, os valores passados ​​devem ser todos do mesmo tipo. Em outras palavras, os parâmetros rest atuam como marcadores de posição para vários argumentos do mesmo tipo.

Para declarar um parâmetro de descanso, o nome do parâmetro é prefixado com três pontos, conhecidos como o operador de propagação. O exemplo a seguir ilustra o mesmo.

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

A seguinte saída é exibida na execução bem-sucedida do código acima.

0 
1 
3

Note - Os parâmetros de descanso devem ser os últimos na lista de parâmetros de uma função.

Função Anônima

As funções que não estão associadas a um identificador (nome da função) são chamadas de funções anônimas. Essas funções são declaradas dinamicamente em tempo de execução. As funções anônimas podem aceitar entradas e retornar saídas, assim como fazem as funções padrão. Uma função anônima geralmente não está acessível após sua criação inicial.

As variáveis ​​podem ser atribuídas a uma função anônima. Essa expressão é chamada defunction expression.

A seguir está a sintaxe para função anônima.

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

Example − Anonymous Function

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

A seguinte saída é exibida na execução bem-sucedida do código acima.

hello

Example − Anonymous Parameterized Function

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

A seguinte saída é exibida na execução bem-sucedida do código acima.

The product : 200

O Construtor de Função

A declaração de função não é a única maneira de definir uma nova função; você pode definir sua função dinamicamente usando o construtor Function () junto com o novo operador.

A seguir está a sintaxe para criar uma função usando o construtor Function () junto com o novo operador.

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

O construtor Function () espera qualquer número de argumentos de string. O último argumento é o corpo da função - ele pode conter instruções JavaScript arbitrárias, separadas umas das outras por ponto e vírgula.

O construtor Function () não recebe nenhum argumento que especifique um nome para a função que ele cria.

Example − Function Constructor

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

No exemplo acima, o construtor Function () é usado para definir uma função anônima. A função aceita dois parâmetros e retorna seu produto.

A seguinte saída é exibida na execução bem-sucedida do código acima.

The product : 200

Recursão e funções JavaScript

Recursão é uma técnica para iterar uma operação fazendo com que uma função se chame repetidamente até chegar a um resultado. A recursão é melhor aplicada quando você precisa chamar a mesma função repetidamente com diferentes parâmetros de dentro de um loop.

Example − Recursion

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

No exemplo acima, a função chama a si mesma. A seguinte saída é exibida na execução bem-sucedida do código acima.

720

Example − Anonymous Recursive Function

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

A função chama a si mesma usando um par de parênteses (). A seguinte saída é exibida na execução bem-sucedida do código acima.

Hello World

Funções Lambda

Lambda se refere a funções anônimas na programação. As funções lambda são um mecanismo conciso para representar funções anônimas. Essas funções também são chamadas deArrow functions.

Função Lambda - Anatomia

Existem 3 partes para uma função Lambda -

  • Parameters - Uma função pode opcionalmente ter parâmetros.

  • o fat arrow notation/lambda notation (=>): Também é chamado como o operador vai para.

  • Statements - Representa o conjunto de instruções da função.

Tip - Por convenção, o uso de um parâmetro de uma única letra é encorajado para uma declaração de função compacta e precisa.

Expressão Lambda

É uma expressão de função anônima que aponta para uma única linha de código. A seguir está a sintaxe para o mesmo.

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

Example − Lambda Expression

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

O exemplo declara uma função de expressão lambda. A função retorna a soma de 10 e o argumento é aprovado.

A seguinte saída é exibida na execução bem-sucedida do código acima.

20

Declaração Lambda

É uma declaração de função anônima que aponta para um bloco de código. Essa sintaxe é usada quando o corpo da função abrange várias linhas. A seguir está a sintaxe do mesmo.

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

Example − Lambda Statement

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

A referência da função é retornada e armazenada na variável msg. A seguinte saída é exibida na execução bem-sucedida do código acima.

function  invoked

Variações Sintáticas

Parênteses opcionais para um único parâmetro.

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

Chaves opcionais para uma única instrução. Parênteses vazios para nenhum parâmetro.

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

Expressão de função e declaração de função

Expressão de função e declaração de função não são sinônimos. Ao contrário de uma expressão de função, uma declaração de função é limitada pelo nome da função.

A diferença fundamental entre os dois é que as declarações de função são analisadas antes de sua execução. Por outro lado, as expressões de função são analisadas apenas quando o mecanismo de script as encontra durante uma execução.

Quando o analisador JavaScript vê uma função no fluxo de código principal, ele assume a declaração da função. Quando uma função vem como parte de uma instrução, é uma expressão de função.

Elevação de Função

Como as variáveis, as funções também podem ser içadas. Ao contrário das variáveis, as declarações de função quando içadas, içam a definição da função em vez de apenas içar o nome da função.

O fragmento de código a seguir ilustra a elevação de função em JavaScript.

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

A seguinte saída é exibida na execução bem-sucedida do código acima.

foo

No entanto, as expressões de função não podem ser içadas. O trecho de código a seguir ilustra o mesmo.

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

Expressão de Função Imediatamente Invocada

As Expressões de Função Imediatamente Chamadas (IIFEs) podem ser usadas para evitar içamento de variáveis ​​de dentro dos blocos. Ele permite o acesso público aos métodos, ao mesmo tempo que mantém a privacidade das variáveis ​​definidas na função. Esse padrão é chamado de função anônima autoexecutável. Os dois exemplos a seguir explicam melhor esse conceito.

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

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

Ambos os exemplos renderizarão a seguinte saída.

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

Funções Geradoras

Quando uma função normal é chamada, o controle fica com a função chamada até que ela retorne. Com geradores no ES6, a função do chamador agora pode controlar a execução de uma função chamada. Um gerador é como uma função regular, exceto que -

  • A função pode devolver o controle ao chamador a qualquer momento.

  • Quando você chama um gerador, ele não funciona imediatamente. Em vez disso, você obtém um iterador. A função é executada quando você chama o próximo método do iterador.

Os geradores são denotados por sufixo da palavra-chave de função com um asterisco; caso contrário, sua sintaxe é idêntica às funções regulares.

O exemplo a seguir ilustra o mesmo.

"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); 
}

Os geradores permitem a comunicação bidirecional entre o chamador e a função chamada. Isso é feito usando oyield palavra-chave.

Considere o seguinte exemplo -

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

A sequência da função do gerador é a seguinte -

  • Gerador iniciado em estado pausado; iterador é retornado.

  • O it.next () retorna “Qual é o seu nome”. O gerador está em pausa. Isso é feito pela palavra-chave yield.

  • O call it.next (“Ethan”) atribui o valor Ethan ao nome da variável e produz “Qual é o seu esporte favorito?” Novamente o gerador está em pausa.

  • O call it.next (“Cricket”) atribui o valor Cricket à variável sport e executa a instrução de retorno subsequente.

Portanto, a saída do código acima será -

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

Note - As funções do gerador não podem ser representadas usando as funções de seta.

Funções de seta

As funções de seta introduzidas no ES ajudam a escrever as funções em JavaScript de maneira concisa. Vamos agora aprender sobre o mesmo em detalhes.

ES5 e funções anônimas

JavaScript faz uso intenso de anonymous functions. Uma função anônima é uma função que não possui um nome associado a ela. Funções anônimas são usadas durantefunction callback. O exemplo a seguir ilustra o uso de uma função anônima no ES5 -

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

O exemplo acima passa uma função anônima como um parâmetro para o pré-definido setTimeout() function. A função setTimeout () retornará a função anônima após 1 segundo.

A seguinte saída é mostrada após 1 segundo -

Learning at TutorialsPoint is fun!!

Sintaxe da função de seta

ES6 apresenta o conceito de arrow function para simplificar o uso de anonymous function. Existem 3 partes para uma função de seta, que são as seguintes -

  • Parameters - Uma função de seta pode opcionalmente ter parâmetros

  • The fat arrow notation (=>) - Também é chamado de operador vai para

  • Statements - Representa o conjunto de instruções da função

Tip - Por convenção, o uso de um parâmetro de uma única letra é encorajado para uma declaração de função de seta compacta e precisa.

Sintaxe

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

OU

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

OU

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

Exemplo: função de seta em ES6

O exemplo a seguir define duas expressões de função add e isEven usando a função de seta

<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>

A saída do código acima será conforme mencionado abaixo -

30
true

Array.prototype.map () e função de seta

No exemplo a seguir, uma função de seta é passada como um parâmetro para o Array.prototype.map() function.A função map () executa a função de seta para cada elemento do array. A função de seta, neste caso, exibe cada elemento na matriz e seu índice.

<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>

A saída do código acima será conforme fornecido abaixo -

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

Exemplo: window.setTimeout () e função de seta

O exemplo a seguir passa uma função de seta como um parâmetro para o setTimeout() function. osetTimeout() função irá retornar a função de seta após 1 segundo.

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

A seguinte saída é mostrada após 1 segundo -

Learning at TutorialsPoint is fun!!

Função de seta e “este”

Dentro de uma função de seta, se usarmos this pointer, ele apontará para o escopo léxico envolvente. Isso significa que as funções de seta não criam um novothis pointerinstância sempre que for invocado. As funções de seta fazem uso de seu escopo envolvente. Para entender isso, vejamos um exemplo.

<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>

Quando uma função anônima é usada com setTimeout(), a função é chamada após 2.000 milissegundos. Uma nova instância de“this”é criado e sombreia a instância da função de aluno. Então, o valor dethis.firstName e this.lastName será undefined. A função não usa o escopo léxico ou o contexto da execução atual. Este problema pode ser resolvido usando umarrow function.

A saída do código acima será a seguinte -

undefined undefined
Mohammad Mohtashim