How do anonymous functions work?

38

I know they are functions that do not have the specified name, but what is the purpose?

  • Is recursion possible with anonymous functions? Ex: Fibonacci sequence.

(function(x, y) {
  alert(x + y);
})(5, 5); // Função para somar duas variáveis
    
asked by anonymous 20.03.2014 / 16:23

5 answers

18

You can implement using recursion yes, just use the variable you assigned the function to and call it:

var fibonacci = function(num)
{
   if(num==1 || num==2)
       return 1;
   else
       return fibonacci(num-1) + fibonacci(num-2); 
};

jsfiddle

Purposes of an anonymous function

Pass as if it were any object

The purpose of an anonymous function is to allow it to pass as if it were an object, which you can assign to a variable, regardless of whether there is a name for the function.

Protecting variables using an anonymous function

Protecting variables against misuse is one of the purposes you've just met for anonymous functions. It would be the equivalent of creating private members, as is possible in many languages.

In the fibonacci example, if you want to protect the variable used to assign the function, you could do this:

var fibonacci = (function() {
    var fnc = function(num)
    {
       if(num==1 || num==2)
           return 1;
       else
           return fnc(num-1) + fnc(num-2); 
    };
    return fnc;
})();

In this way, you would not be able to change the internal dependency of the function after it has already been created. It will no longer be possible to change the fnc variable, since it is within the context of the anonymous function whose reference is lost after calling it.

Basic structure:

var obj = (function() {
    // declarações a serem protegidas
    var a, b, c;
    // retornando um objeto construído a partir de a, b e c
    return obj;
})();
    
20.03.2014 / 16:31
22

Answering your question literally "How do anonymous functions work?" :

Anonymous functions are very important to understand some of the concepts of JavaScript operation, they are functions that do not depend on names, are only declared and stored in a variable.

This is an anonymous function: function(){alert('foo');

One of the best practices for using it is to create JavaScript Closures , because:

  

"Knowing JavaScript and not knowing Closures, is the same thing as knowing Java and not knowing Classes."

For this reason, the understanding of Closures and Anonymous Functions is of the utmost importance.

Definition of Closures:

  

Closure in English means closure, in the sense of keeping, put in a closed place.

That is, you would store a variable in a function that may have parameters or not. It can return a value and make it immutable, or else just perform commands with no return.

Explanation with Examples:

Here's how a simple anonymous function would work with a function with no arguments:

var anonima = function(){ alert('executou') };
anonima(); //executa a função anônima

Now one with parameter:

var anonima = function(n){ alert(n) };
anonima(2);

We can also create a closure with anonymous functions, such as a sum of two numbers:

    var anonima = function(number1){
  return function(number2){ alert(number1+number2) };
};
var closure = anonima(2); //salva na variavel closure a funcao que manda o parâmetro number1
closure(3); //manda o parâmetro number2 e executa a função final

Closures become great for storing in some variables operations that call different functions by returning an operation result or function.

Another very good thing about Closures would be the creation of encapsulated classes, such as a Company class:

function Empresa(nome){
    //privates
    var _funcionarios       = [];
    var _ordenaFuncionarios = function(){
        return _funcionarios.sort();
    }
    //public's
    return {
        adicionaFuncionario: function(funcionario) {
            _funcionarios.push(funcionario);
            //return this;
        },
        meusFuncionarios: function(){
            return _ordenaFuncionarios(_funcionarios).join(", ");
        }
    };
}

And see how easy it is to add employees, and print them sorted:

var p = new Empresa("Foo Ltda");
p.adicionaFuncionario("João da Silva");
p.adicionaFuncionario("Maria da Rosa");
alert(p.meusFuncionarios()); //João da Silva, Maria da Rosa.

Note that you have "return this" commented, uncomment test and so you will be able to use method chaining like this:

var p = new Empresa("Foo Ltda");
alert(p.adicionaFuncionario("João da Silva")
    .adicionaFuncionario("Maria da Rosa")
    .meusFuncionarios()); //Joao da Silva, Maria da Rosa

Another thing, you can avoid creating global variables using Closures, as follows:

cor = "azul";

(function(){ //função anônima
    var cor = "#FF0000";
    document.body.style.background = cor; //deixa o fundo da pagina vermelho
})();
alert(cor); //azul

Javascript closures are very good for a lot of things, anonymous functions as well. As you can see, it's worth studying about it:)

    
20.03.2014 / 17:20
13

In JavaScript, functions are said to be "first class members". This means that you can instantiate them, assign them to variables, or even create them dynamically at runtime (note: 99% of the time I do not recommend). Each instantiated function is carrying an object of class Function .

An anonymous function is not very different from a named function. These two definitions are in fact equivalent:

function foo() { return "bar"; }
var foo = function() { return "bar"; }

Is there a difference?

No . The apparent difference (as pointed out in the @Gabriel Gartz response) is due to the fact that in JavaScript the variable definitions are automatically brought to the top of their lexical scope.

This means that when the interpreter sees:

console.log(naoAnonima()); // 'foo'
console.log(anonima()); // undefined

var anonima = function () {return 'bar';};
function naoAnonima() {return 'foo'; }

It automatically converts to:

var anonima; // A definição da variável veio pra cima, a atribuição não
function naoAnonima() {return 'foo'; } // A definição da função veio pra cima

console.log(naoAnonima()); // Aqui naoAnonima já está definida
console.log(anonima()); // A variavel anonima existe, mas ainda não aponta pra uma função

anonima = function () {return 'bar';}; // A partir daqui anonima refere-se a uma função

What is it for?

You do not always need a name for your job. It's that simple! If you are going to use the newly defined function in an event handler, or a callback for Ajax, etc., there is no need to put this function in a variable / give it a name. Just create the function and assign it where you need it (first class, remember?).

window.onload = function() { /* essa função não precisa de um nome */ };

Is recursion possible?

There is a more theoretical rather than practical interest called " Y Combinator , that I will not show here, anyone interested here has some links explanatory (in English). It basically allows recursion to be implemented without any variable or function declaration. That is, unlike the other answers - that "cheat" a little, giving a name to its anonymous function (!) - this solution works even if there is no reference to the function itself.

Y(function (fac) {
    return function (n) {
        return n <= 2 ? n : n * fac(n - 1);
    };
})(5); // 120

But if this "cheating" is admitted (in practice, there is not much benefit in "smart" solutions - rather than being clear and efficient), then to get a recursive effect on an anonymous function, just get it as a function argument:

var fat = function(fn, n) {
    if ( n <= 2 )
        return n;
    return n * fn(n - 1);
};

... and pass herself as an argument in your call!

fat(fat, 5); // 120

That is, the function is not recursive (since you could call it by passing something else as the first argument), but it behaves recursively.

    
20.03.2014 / 17:38
6

Anonymous functions they do not have an ID in the execution scope of javascript, however they can be assigned to variables, earning by becoming accessible only when this variable is accessible.

Example:

console.log(naoAnonima()); // 'foo'
console.log(anonima()); // undefined

var anonima = function () {return 'bar';};
function naoAnonima() {return 'foo'; }

console.log(naoAnonima()); // 'foo'
console.log(anonima()); // 'bar'

As can be seen in the example, the anonymous function is only accessible as soon as the variable as well.

If you do not use strict mode ( use strict ) you can access the reference of an anonymous function by means of the arguments.callee exposed in your context.

Example:

function () {
    arguments.callee; // Aqui está referencia pra sua função
};

Using strict mode, this will cause you an exception.

So if you implement the fibonnaci example, you can first declare a variable that will save the reference of your anonymous function and use it within the anonymous function.

var fib = function (n) {
   if (n <= 2) return 1;
   return fib(n - 1) + fib(n - 2);
};

In this case fib exists inside the anonymous function because when the function is being accessed by itself, the variable has already been assigned. Enabling recursion.

One way to do just a didactic example of ES3 was to use arguments.callee for this:

(function (n) {
   if (n <= 2) return 1;
   return arguments.callee(n - 1) + arguments.callee(n - 2);
})(10); // 55

Notice that no function was assigned to the function. That is, after it has been executed and finalized, it will be marked by the garbage collector to be deleted, because in that case there is no longer any reference to it.

In ES5 you do not have access to the arguments.callee property in strict mode, but you can hide the function that applies recursion within an anonymous function if you do not want to expose it. Example:

(function (n) {
   // fib não está exposto
   return (function fib(n) {
     if (n <= 2) return 1;
     return fib(n - 1) + fib(n - 2);
   })(n);
})(10); // 55

In this case even if you name the anonymous function, its internal fib function is inaccessible.

Purpose:

Anonymous functions exist to streamline and simplify encoding, for example if you want to isolate a scope of variables, you can simply auto-execute an anonymous function for that.

It is very common in javascript to assign functions to properties or pass them as an argument, anonymous functions simplify coding and you do not need to name them to make these assignments, leaving your code simpler.

    
20.03.2014 / 16:38
3

It also fits into the Javascript command setting setting

They receive one or more functions as arguments or have a function as output. Through them it is possible to create what are called functions factories which are functions that from other functions are able to perform more complex actions. The context itself also tells us: Unnamed functions, moreover, it includes as main characteristic the concept of recursion.

<script>

    var n = parseInt(prompt('Entre com a seleção da cor : '));

    (function(n){

        var cor = [
            '#FF0000',
            '#000000',
            '#C9CCCC'
        ];



        for(var i = 0; i < cor.length; i++) {
            document.body.style.background = cor[i + n];
            break;
        }


        if (n >= cor.length)
            alert('Error = Cor da seleção deve ser < ' + cor.length);
        else
            alert('Cor Selecionada : ' + cor[i + n] + ' ');

    })(n);

</script>
    
15.06.2015 / 19:50