Hacker News new | past | comments | ask | show | jobs | submit login
How JavaScript closures work under the hood (dmitryfrank.com)
83 points by dimonomid on Sept 6, 2015 | hide | past | favorite | 16 comments



I've noticed that a lot of people (though not the author of this article) confuse the terms "lambda expression" and "closure". Perhaps this confusion is worth taking a moment to address here.

A closure, as explained in the article, is a pair of a code pointer and an environment. It is an object "inside the machine" that exists at runtime.

A lambda expression is a syntactic entity, a piece of source code: something you can see on the screen.

A lambda expression evaluates to a closure, just as an integer literal (a string of digits) evaluates to an integer, or a 'new' expression evaluates to an instance (object).


A closure is a procedure that captures its free variables where those free variables are resolved in the lexical context.

A lambda procedure is just an anonymous procedure.

A lambda is not necessary a closure and a closure is not necessary a lambda.


Can't talk about closures without mentioning this excellent piece http://mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun...


Funny how all these articles make me think that lambda/closures are a very very nice syntax to create linguistic friendly structure. Automatically embedding of lexical scope avoid unnecessary names, assignments and side effects. Similarly to this talk https://news.ycombinator.com/item?id=3717715 where the author demonstrates how often we write classes with a bit of state, a constructor, and a single method [1].. which is a what a function does for us.

Some programming classes takes some time to describe this habit of unnecessary wrapping[2]. From

    ```
    if bool_var then true else false
    ```
, to theses functions-written-as-classes, or even, depending on the language you use, function that wraps other functions disguised as operators

    ```
    map(function add(x, y) { return x + y }, list)
    // aka `map + list` in deeply functional languages
    ```
[1] Java had many single method interfaces that can now be replaced by lambdas

[2] see Dan Grossman proglang on Coursera (taken from his original classes at UoWashington)


There is technically a pretty significant difference between

    +
    function add(x, y) { return x + y; }
in general in strict, effectful languages. The transformation is called "eta expansion" (technically, I performed two eta expansions and an un-currying) and we really would like it to be valid—it implies conceptual freedom to introduce and eliminate abstractions, but it rarely is. The issue being that it introduces thunks where computation or effects can hide.


Lua uses a concept called "upvalues" to refer to variables from enclosing scopes. The main observation here seems to be that you can statically determine a unique index for all local variables in any enclosing scope. I'm not sure exactly how the details work in cases where there are sibling scopes, but anyway it seems like a useful concept and i am surprised the concept/terminology is not more common.


This technique is very old -- it goes back at least to Pascal, IIRC, and probably to Algol 60. It certainly was used in Scheme implementations in the late 1970s. I haven't heard the term "upvalue" before, though.


That's sort of my point. There seems to be some established knowledge about how you can address "upvalues" within closures but very little shared terminology or literature about it.


Tcl uses uplevel to evaluate a block of code in the current context.


Every implementation of a closure I've encountered creates a new Capture class which stores references/copies of all variables the closure uses. I think they do this even if the closure doesn't reference any local variables - only class-level ones. In this case, wouldn't it be better to just implement it as a local function of the parent class instead of creating a new class? Or does it not matter because the cost of calling this.foo is negligibly similar to this.parent.foo?


AFAICT Closures are still much faster than Function.prototype.bind.

(http://jsperf.com/bind-vs-closure-setup/44)

Could anyone who knows more about the implementation details point to an explanation of what's going on under the surface?



That's vert interesting. Thank you.


Here is an answer I wrote about it a while back http://stackoverflow.com/questions/17638305/why-is-bind-slow...

Let me know if you have any questions about it


That's a great answer, thank you.


How could test1 here ever be faster than test2? The functions are identical but calling test1 will always incur twice the actual function invocations, first to the bound function and then to _test1.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: