How do anonymous functions work?

Asked

Viewed 22,471 times

43

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

  • Is it possible to recur with anonymous functions? Ex: Fibonacci sequence.

(function(x, y) {
  alert(x + y);
})(5, 5); // Função para somar duas variáveis

5 answers

23

Literally answering your question "How anonymous functions work?":

Anonymous functions are very important to understand some of the concepts of how Javascript works, 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, for:

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

That is why the understanding of Closures and Anonymous Functions is of utmost importance.

Definition of Closures:

Closure in English means closure, in order to store, put in a closed place.

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

Explanation with Examples:

See how a simple anonymous function would work with a function without 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 becomes great for storing some operations in variables that call different functions returning an operation or function result.

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

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 becomes to add employees, and print them ordered:

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.

Notice that you have "Return this" commented, uncomment test and so you will be able to use method chaining in this way:

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 too. As you can see, it’s worth taking a look at :)

  • I don’t think you understand very well what are closures. Or maybe you are - the second half of your answer describes closures very well. However, what you refer to as "storing a function in a variable" is not closures, but "first class functions". In other words, a language may have first-class functions but have no lexical scope - and therefore not support closures.

  • You meant that the functions that I added at the beginning that were not encapsulated are not closures?

  • funcaoInterna is a closure. The two internal functions to Empresa also are. The rest are not. To be a closure, the function has to reference some variable of the lexical scope above of it (e.g., when funcaoInterna access number1 - which belongs to the lexical scope of funcaoExterna).

  • There’s a typo there in the first example, right? I think we need to close function(){alert('foo'); . . .

20


You can implement using recursion yes, just use the variable itself to which you assigned the function 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

To pass as if it were any object

The purpose of an anonymous function is exactly to allow you to pass it as if it were any 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 that ended up meeting for anonymous functions. It would be the equivalent of creating private members, as is possible in several languages.

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

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

This way, there would be no way to change the internal dependency of the function after it has already been created. It will no longer be possible to change the variable fnc, because it is within the context of the anonymous function, whose reference is lost, soon after calling the same.

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;
})();
  • I think the question is not about Fibonacci but about Anonimas functions, Fibonacci was an example of use case.

  • 2

    I think the real question was: "How to use recursion in an anonymous method, since it does not have a name?"

  • agree, I think it was worth editing the title :)

  • Not to be pedantic, but when you assign a function to a variable, does it stop being anonymous? (i.e. you gave it a name) Your answer is technically correct, but everything described here would be equally possible with appointed functions.

  • 1

    What about protecting variables within an anonymous function? I mention that the function is lost immediately after calling it... something like (function () { })()

  • @Miguelangelo OK, in this case there is in fact a small advantage. Although it is possible to do (function nome() { })() and the variables within it would remain protected, the function itself would be accessible through the name and could be used incorrectly.

Show 1 more comment

13

In Javascript, functions are called "first class members". This means you can instantiate them, assign them to variables, or even create them dynamically at runtime (note: 99% of the time I don’t recommend). Each instantiated function is carrying a class object 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"; }

There is difference?

Not. The apparent difference (as pointed out in Reply by @Gabriel Gartz) is due to the fact that in Javascript the variable settings are automatically brought to the top of your lexical scope.

That means 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 good is?

You don’t always need a name for your function. It’s that simple! Whether you’re going to use the newly defined function in an event handler, or in 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 needed (first class, remember?).

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

Recursion is possible?

There is a trick more theoretical than practical interest called "Y Combinator", that I will not demonstrate here, who is interested here has some links explanatory (in English). It basically allows recursion to be implemented without any variable or function statements. 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 - better that they are clear and efficient), then to get a recursive effect in an anonymous function just make it receive as argument a function:

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

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

fat(fat, 5); // 120

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

6

Functions Anonimas they do not have an identification in the javascript execution scope, but can be assigned to variables, gaining access 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 anonymity function it is only accessible so the variable also.

If you do not use the strict mode (use strict) you can access the reference of an anonymous function through the property Arguments.callee exposed in its context.

Example:

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

Using strict mode, this will cause you an exception.

So if you are to implement the Fibonnaci example, you can first declare a variable that will store the reference of your anonymity function and use it within the anonymity function.

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

In this case fib exists within the anonymity function because when the function is being accessed by itself, the variable has already been assigned. Allowing recursion.

A textual example of ES3 was to use the arguments.callee for that reason:

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

Note that no function has been assigned to any variable. That is, after it has been executed and finished, it will be marked by Garbage Collector to be eliminated, in which case there is no further reference to it.

At ES5 you do not have access to property arguments.callee in strict mode, but you can hide the function that applies recursion within an anonymous function if you do not want to expose this one. 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 anonymity function, its internal Fib function is inaccessible.

Purpose:

The functions Anonimas exist to streamline and simplify coding, for example, if you want to isolate a range of variables, you can simply auto-execute an anonymous function for this.

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

  • +1 for the use of arguments.callee. Although in practice not recommended, this was the only example of anonymous recursive function in all responses (the other "cheating" a little - giving a name to the anonymous function!).

  • Thanks @mgibsonbr, put only for educational purposes even, do not recommend the use.

  • @mgibsonbr see my answer now is no longer cheating and do not use the arguments.callee :P

3

It also fits the definition of Higher order function javascript

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 that are functions that from other functions are able to perform more complex actions. The context itself already tells us : Unnamed functions, moreover, it includes as its main feature the concept of recursiveness.

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.