4

Normally, I see function closure achieved by the form

var closedF = (function()
{
    return function(){/* return value */}
})();

so that calling closedF() returns the return value from the inner function. But I want to create closedF using a function declaration (the above is a function expression) so that it is defined at parse time. I.e.

function closedF()
{
    return function(){/* return value */}
}

but this doesn't work because when calling closedF(), it returns the inner function as opposed to the return value of the inner function. Note: with the above declaration I could use closedF()(), but that's just inelegant.

Is this possible?

p.s. As is usually the case there are many ways for me to solve my particular programming problem, but I actually want someone to show me that closed-over functions aren't "second-class citizen" functions in JS.

Jeff
  • 1,230
  • 1
  • 11
  • 21

4 Answers4

3

Your problem has not necessarily anything to do with function expression vs function declaration.

In the both cases you showed, you don't get the return value of the inner function.

You could get it by just calling the inner function and return it's value:

function closedF() {
    return (function(){
        /* return value */
    }()); // <- calling the inner function here
}

The disadvantage is that the inner function will always be defined anew when calling the outer function. You could prevent this by caching the inner function as a property of the outer function:

function closedF() {
    var func = closedF.__func ||  (closedF.__func = function(){
        /* return value */
    });
    return func();
}

However, this might be more confusing than helpful.

Easier is to execute the outer function immediately and assign the returned function to a variable, as @James Long shows in his answer.

Update:

You could also do this:

(function() {
    window.closedF = function() {

    };
}());

though both are function expressions

Community
  • 1
  • 1
Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
  • I'm marking this as the answer even though it seems like what I'm trying to do is impossible, because your second example is the only option (posted here) I hadn't considered before. – Jeff Jul 08 '11 at 20:59
  • @Jeff: I think I still haven't fully understood what you actually want. But have a look at my update, maybe it comes closer to what you want. It should not matter whether you use a function expression or declaration. What matters is which function you want and have to execute at which time. E.g. if the sole purpose of calling the outer function is to execute the inner function, then why not make the inner function directly accessible? We could probably help you better if you describe the actual problem you are trying to solve (as @cwolves said). – Felix Kling Jul 08 '11 at 21:05
  • "In the both cases you showed, you don't get the return value of the inner function." @Felix Kling Why doesn't `closedF()` assuming the first example get the return value of the inner function? – Jeff Jul 08 '11 at 21:08
  • Yeah, the last example is further from what I want. I want the inner function (a "closed-over function") that is defined at parse-time. Does that make sense? This question is really not about a particular problem--just inspired by one. – Jeff Jul 08 '11 at 21:11
  • @Jeff: "Why doesn't closedF() assuming the first example get the return value of the inner function?" Because you are not calling the inner function. If you call `closedF()` you will invoke the outer function, which just returns the inner function. (b) Ok I think I understood. Then no, there is no way (does this even make sense?). The inner function does and cannot exist until the outer function is called. – Felix Kling Jul 08 '11 at 21:17
  • @Jeff: But in the first example, `closedF` is assigned at run time not at parse time. You only have to choices to make an inner function available to the outside: Either you return it from the outer function or you assign it to a higher scope. But both will happen at *run time* because you have to execute the code. – Felix Kling Jul 08 '11 at 21:37
  • Wow, brain cramp! Just realized my first example wasn't what I meant. It should make more sense now. Anyway, I maintain that it makes sense, because global, closed-over functions--**with private, persistent variables**--do exist (as is possible with the first example). Thanks. – Jeff Jul 08 '11 at 21:41
  • @FelixKling let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1275/discussion-between-jeff-and-felix-kling) – Jeff Jul 08 '11 at 21:42
2

This isn't possible. The only way to get a function from within a closure is to actually execute the wrapping function which, of course, can't happen during compile.

The code you're actually looking for is:

var closedF = function(){
    return function(){
       // do stuff
    }
}(); // <-- note the (), which immediately calls the outer function

Ultimately, there isn't even a valid use-case for what you're asking for. The point of a closure is that you can get references to external variables passed-in during program execution that are available to a specific function. If you're trying to do this during compile, you already have access to anything you're trying to get since no coe has been executed yet. Therefore there is no need for a closure.

If you post exactly what you're trying to do, there may be another solution.

Mark Kahn
  • 81,115
  • 25
  • 161
  • 212
  • Maybe you want to join the discussion (if it takes place): http://chat.stackoverflow.com/rooms/1275/discussion-between-jeff-and-felix-kling – Felix Kling Jul 08 '11 at 21:44
1

You mean something like this:

function closedF() {
    return function () {
    }
}

Yup, that's perfectly acceptable

Edit: Reading the comments, I think you need a self-executing anonymous function:

var closedF = (function () {
    return function () {
    };
}());

This will create a function that can simply be executed by calling closedF(), but I don't know if it's possible as a declaration.

James Long
  • 4,237
  • 1
  • 16
  • 26
  • 1
    I _think_ he wants that immediately executed so that closedF == the inner function (e.g. if you added `()` on the end of his example) – Mark Kahn Jul 08 '11 at 20:03
  • @James Long You're right, this is what I meant to put for my first example (but not what I'm after). – Jeff Jul 08 '11 at 22:10
1

Did you consider passing a function as a parameter?

function closedF(fn){
    return fn;
}

And to use it:

var fnParam = function(){...};
...
closedF(fnParam);
Mic
  • 23,536
  • 8
  • 55
  • 69
  • http://en.wikipedia.org/wiki/Identity_operator is an interesting topic, but how is it connected to the question? – katspaugh Jul 08 '11 at 20:13
  • While trying to understand the question I thought it could be this, may be not after all. – Mic Jul 08 '11 at 20:16