0

In this example it seems that a callback is accessing another parameter (without having to provide the argument again).

Excerpt from the link above

var SimplePropertyRetriever = {
    getPrototypeEnumerables: function(obj) {
        return this._getPropertyNames(obj, false, true, this._enumerable);
    },

    _enumerable: function(obj, prop) {
        return obj.propertyIsEnumerable(prop);
    },

    _getPropertyNames: function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
        ...
    }
}

As seen:

  • this._enumerable is passed to _getPropertyNames
  • _enumerable accepts a parameter called obj
  • obj is not explicitly passed down though, so it seems that when the callback is passed to _getPropertyNames it somehow accesses its first argument, which is obj

To test it, I tried the below, which did not work.

function myFunc2(para, callback) {
    console.log(`Para: ${para}`);
    callback();
}
myFunc2(42, (para) => console.log(para));

Any idea what I am missing here?

6
  • Pass para - "console.log(Para: ${para}, callback: ${callback(para)});" Commented Apr 23, 2018 at 9:51
  • "which did not work": what were you expecting exactly and how does it not work? The callback function you pass to your call logs the param it is given, but you give it none when you call it: callback();. This para is not the same than in your callback defined in your call, you should distinct them to avoid confusion: myFunc2(42, (x) => console.log(x)); Commented Apr 23, 2018 at 9:55
  • @gurvinder372 That's exactly my point. this._enumerable does not pass obj down. To my understanding, I would have written it as this.enumerable(obj, prop) Commented Apr 23, 2018 at 9:56
  • @Kaddath Yep, I know, which is why I don't get how the linked example work. _enumerable accesses obj in _getPropertyNames, when obj is never passed to it. Commented Apr 23, 2018 at 9:58
  • 1
    No, the tricky part here is that this line return this._getPropertyNames(obj, false, true, this._enumerable); doesn't call at all the this._enumerable function. It gives it as param to this._getPropertyNames so that includePropCb is now this function. It has yet to be called in this._getPropertyNames under that name (if needed). this._getPropertyNames already has obj as a parameter, so he can use it with the function if we want to. Commented Apr 23, 2018 at 9:59

1 Answer 1

1

I would suggest you understand Closures and Variable Scopes in JavaScript.

For the code snippet you mentioned above, since your callback needs an arg 'para' you can pass it and log it. If you don't want to pass it you can just add it to global object( 'window' object in case of browser).

This is because your anonymous callback function expects 'para' variable first in it's own body, next it will try to search in it's parent's body which in this case is global object.

For the below example,

function myFunc2(para, callback) {
    window.para = para;
    console.log(`Para: ${para}`);
    callback();
}
myFunc2(42, () => console.log(para));

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. General follow-up question here if I may: How come the callback does not have access to variables in myFunc2, when it gets executed inside that function? As we know, functions have access to variables in outer scopes (which for the callback include both the outer function, as well as the global scope).
It's absolutely true that "functions have access to variables in outer scopes", and this is valid if function is declared inside its outer function declaration and not while invocation. So in your case the callback resides in global context while execution and not in "myFunc2". I hope this makes sense.
Ah, because scope is determined statically at compile-time, not run-time, and the execution only happens run-time?
I would like to call JavaScript an interpreted language ( this can be debated). I belive JavaScript follows "lexical scoping" so scope is decided by knowing where the variable sits physically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.