Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definition of 'closures'

Let me ask one question. It's about closures in JavaScript, but not about how they work.

David Flanagan in his "JavaScript The Definitive Guide 6th Edition" wrote:

...Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them....

Is this correct? Can I call every function (function object + it's scope) a "closure"?

And stacks' tag "closures" says:

A closure is a first-class function that refers to (closes over) variables from the scope in which it was defined. If the closure still exists after its defining scope ends, the variables it closes over will continue to exist as well.

In JavaScript every function refers to variables from the scope in which it was defined. So, It's still valid.

The question is: why do so many developers think otherwise? Is there something wrong with this theory? Can't it be used as general definition?

like image 443
Ivan Avatar asked Jun 26 '15 22:06

Ivan


2 Answers

Technically, all functions are closures. But if the function doesn't reference any free variables, the environment of the closure is empty. The distinction between function and closure is only interesting if there are closed variables that need to be saved along with the function code. So it's common to refer to functions that don't access any free variables as functions, and those that do as closures, so that you know about this distinction.

like image 79
Barmar Avatar answered Sep 28 '22 08:09

Barmar


It's a tricky term to pin down. A function that's simply declared is just a function. What makes a closure is calling the function. By calling a function, space is allocated for the parameters passed and for local variables declared.

If a function simply returns some value, and that value is just something simple (like, nothing at all, or just a number or a string), then the closure goes away and there's really nothing interesting about it. However, if some references to parameters or local variables (which, mostly, are the same) "escape" the function, then the closure — that space allocated for local variables, along with the chain of parent spaces — sticks around.

Here's a way that some references could "escape" from a function:

function escape(x, y) {
  return {
    x: x,
    y: y,
    sum: function() { return x + y; }
  };
}

var foo = escape(10, 20);
alert(foo.sum()); // 30

That object returned from the function and saved in "foo" will maintain references to those two parameters. Here's a more interesting example:

function counter(start, increment) {
  var current = start;
  return function() {
    var returnValue = current;
    current += increment;
    return returnValue;
  };
}

var evenNumbers = counter(0, 2);
alert(evenNumbers()); // 0
alert(evenNumbers()); // 2
alert(evenNumbers()); // 4

In that one, the returned value is itself a function. That function involves code that makes reference to the parameter "increment" and a local variable, "current".

I would take some issue with conflating the concept of a closure and the concept of functions being first-class objects. Those two things really are separate, though they're synergistic.

As a caveat, I'm not a formalist by basic personality and I'm really awful with terminology so this should probably be showered with downvotes.

like image 21
Pointy Avatar answered Sep 28 '22 10:09

Pointy