Returns undefined

I have:

  • dictionary ( functions

    ) displaying string prefixes for functions
  • function ( get()

    ) that returns a function mapped to string
  • a function ( check()

    ) that checks if there is a function mapped to a string by calling get()

    and casting it to a boolean with !!

    .

When I call get()

with the key in functions

, I expect to check()

return true

; however, it returns false

. I do a dictionary lookup in get()

and print the result type in both functions. Here's the weird part. Type B function

only get()

; in check()

, it undefined

. Apparently the function gets erased or something when I return it. How can I make it check()

accurate?

Here's my simplified code:

var someObject = {
    functions: {
        "a": function () { return 0; },
        "b": function () { return 1; }
    },
    get: ( function ( someVariable ) {
        Object.keys( this.functions ).forEach( ( function ( functionKey ) {
            if ( someVariable.startsWith( functionKey ) ) {
                console.log( typeof this.functions[ functionKey ] );
                return this.functions[ functionKey];
            }
        } ).bind( this ) );
    } ),
    check: function ( stringToCheck ) {
        var returnedFunction = this.get( stringToCheck );
        console.log( typeof returnedFunction );
        return !!returnedFunction;
    }
}

$( document ).ready( function () {
    someObject.check( "a" );
} );

      

Running this code brings up the following:

"function"
"undefined"

      

in the console.

+3


source to share


2 answers


This is because it forEach

does not break early / short-circuiting in the statement return

(it continues with the next iteration and then the function get

returns undefined

). You can rewrite the loop to resolve the violation (say with a simple one for-loop

), or you can return the value after the loop, like so:



var someObject = {
    functions: {
        "a": function () { return 0; },
        "b": function () { return 1; }
    },
    get: ( function ( someVariable ) {
        var func;
        Object.keys( this.functions ).forEach( ( function ( functionKey ) {
            if ( someVariable.startsWith( functionKey ) ) {
                console.log( typeof this.functions[ functionKey ] );
                func = this.functions[ functionKey];
            }
        } ).bind( this ) );
        return func;
    } ),
    check: function ( stringToCheck ) {
        var returnedFunction = this.get( stringToCheck );
        console.log( typeof returnedFunction );
        return !!returnedFunction;
    }
}

      

+2


source


This is because you are returning a function from a callback forEach

. it's no good.

The fix might work as Jack suggested, but the code is simplified:



get: function ( someVariable ) {
        var func;
        Object.keys( this.functions ).some(function ( functionKey ) {
            if ( someVariable.startsWith( functionKey ) ) {
                console.log( typeof this.functions[ functionKey ] );
                func = this.functions[ functionKey];
                return true;
            }
        }, this );
        return func;
    }

      

  • You don't need to wrap the function with parens
  • You don't need to bind, forEach

    and some

    (the one I used) take a parameter thisArg

    .
  • If you use some

    , the iteration stops as soon as the callback returns true. This is more efficient in cases where there are many keys, and also more closely matches what your original code was trying to do. In Jack's version, if the keys are where ['a', 'b', 'aa']

    , you will iterate over all 3 and return "aa", and your code (and mine) stops after the first "a".
+1


source







All Articles