aaronfalloon
aaronfalloon

Reputation: 393

When returning an anonymous function from a function, is the function in the return statement a function declaration or function expression?

This is the code which I got stuck on.

var bind = function(func, thisValue) {

  return function() {

    return func.apply(thisValue, arguments);

  }

}

I've been learning about execution contexts and closures. My guess is that the function in the first return statement is a function expression as it's part of a statement. However, then I don't know how a closure, with reference to func and thisValue, is created.

If it is a function expression, then when bind is called, the anonymous function won't be evaluated there and then and therefore won't have a function object set up with a [[scope]] property containing the scope of bind's execution context. And so, the anonymous function won't have access to func and thisValue through it's [[scope]] property.

So if the code does indeed form a closure, then my guess is wrong and the function in the first return statement must be a function declaration. Or maybe I'm misunderstanding when return is evaluated? Any help on this would be greatly appreciated!

Upvotes: 3

Views: 151

Answers (2)

aaronfalloon
aaronfalloon

Reputation: 393

So I did some digging in the ECMAScript Language Specification and came to the conclusion that the anonymous function that's being returned is a function expression... and it really seems quite simple now. When defining a function using a function declaration, the identifier isn't optional and so an anonymous function can't be defined using a function declaration. Anonymous functions can only be defined using function expressions because with function expressions, the identifier is optional.

I also said this...

If it is a function expression, then when bind is called, the anonymous function won't be evaluated there and then and therefore won't have a function object set up with a [[scope]] property containing the scope of bind's execution context.

I was wrong. The function expression is evaluated when bind() returns. Therefore, a function object is set up for it and everything is scoped as it should be.

I hope I've made some sense. If I've missed anything, please comment!

Upvotes: 2

Halcyon
Halcyon

Reputation: 57719

This seem quite complicated but is actually very simple. What this function does is return a function where the arguments you pass are bound to thisValue.

Here is an example:

var bind = function(func, thisValue) {
    return function() {
        return func.apply(thisValue, arguments);
    }
}

var x = {
    "key": "the value"
};
var y = {
    "key": "the y value"
};

function alert_key() {
    alert(this.key);
}

var bound_function = bind(alert_key, x);
bound_function();   // alerts "the value"
var bound_function2 = bind(alert_key, y);
bound_function2();  // alerts "the y value"

It's important to realize that this in this.key is bound to x because it is the first argument in func.apply(thisValue, arguments)

arguments is a magic JavaScript variable that will contain all arguments passed to the function. So func.apply(thisValue, arguments) really only just passes all arguments along but set the this context to thisValue (or x and y in my example).

Example for extra argument(s):

var bind = function(func, thisValue) {
    return function() {
        return func.apply(thisValue, arguments);
    }
}

var x = {
    "key": "the value"
};

function alert_key(another_value) {
    alert(this.key + " " + another_value);
}

var bound_function = bind(alert_key, x);
bound_function("another value");    // alerts "the value another value"
bound_function("value y");  // alerts "the value value y"

Upvotes: 1

Related Questions