Why is this object property undefined?

23,275

Solution 1

I've solved the problem. Basically, the object in question (that.data[0].cards) has its properties created by a function a() that runs after all the AJAX requests for the necessary XML files have been processed. I allow the requests to run asynchronously, using a counter to determine in the success callback function if a() should be called yet.

After a() runs, function b() is supposed to perform operations on that.data[i].cards. However, b() was running prior to a() being called because of a()'s reliance on the asynchronous requests. So the solution was simply to make a() call b().

So this turned out to be a pretty simple mistake on my part. What made it so confusing was the fact that logging that.data[0].cards to the console showed me that in fact the cards object had already been built, when in fact it had not yet. So the console was providing me with incorrect--or at least unclear--information.

Thanks for everyone's help last night! Upvotes all around :)

Solution 2

I think the object keys have unprintable characters, such can be replicated like this:

var obj = {};
obj["E"+String.fromCharCode(15)] = new Array(15);

console.log(obj);

/*Object
E: Array[15]
__proto__: Object*/

console.log(obj.E)

//undefined

console.log( obj["E"+String.fromCharCode(15)] )

//[]

Edit: you can see if this is the case for your object keys:

var realKeys = [];

for( var key in obj ) {
realKeys.push( [].slice.call( key ).map( function(v){return v.charCodeAt(0);} ).join(" ") );
}

//["69 15"] (69 stands for the letter "E" and 15 was the unprintable character I added manually)

Edit2: Since you can't do that I came up with another way to see if there are unprintable characters:

Copypaste the key string like this: (go all the way as much as you can on both ends so you pick any invisible characters)

Then dump your clipboard like this (Make sure you are using double quotes):

Share:
23,275
maxedison
Author by

maxedison

Updated on October 29, 2020

Comments

  • maxedison
    maxedison over 3 years

    Consider the code below. The first console.log correctly logs the image, and you can see its properties in the image below. However, when I try logging one if its properties to the console, I get undefined!

    console.log(that.data[0].cards); //works -- see image below
    console.log(that.data[0].cards.E); //undefined
    console.log(that.data[0].cards['E']); //undefined
    console.log(that.data[0].cards.hasOwnProperty('E')); //false
    
    var test = JSON.stringify(that.data[0]);
    console.log(test); // {}
    
    for( var key in that.data[0].cards ) {
        console.log('hello????') //doesn't appear in the console
    }
    
    console.log( Object.keys( that.data[0].cards ) ); //[]
    console.log( that.data[0].cards.propertyIsEnumerable("E") ); //false
    console.log( that.data[0].cards.__lookupGetter__( "E" ) ); //undefined
    

    The result in the console:

    enter image description here

    Any idea what's going on here? The xml property inside of that.data[0] should also have properties inside of it -- named the same, in fact, as the properties in cards.

    FWIW, I get the same thing in Firebug (the above console image is Chrome).

  • maxedison
    maxedison over 12 years
    Seems to produce the same result. I did: console.log(that.data[0].cards['E'+String.fromCharCode(15)])‌​;
  • Esailija
    Esailija over 12 years
    That's because your object might have different invisible character than String.fromCharCode(15), it could be 3, 24 or 22 and so on :)
  • pimvdb
    pimvdb over 12 years
    @macedison: And because of @Esailija's reason please copy/paste the exact result of JSON.stringify(that.data[0]) so that it can be investigated
  • maxedison
    maxedison over 12 years
    JSON.stringify(that.data[0]) produces: {"session":"01","xml":{},"cards":{}}. The truth is that the xml object should also have properties inside of it, named the same as the cards object in fact. I also updated my question to include the results of the for loop you suggested, but it doesn't seem to even run.
  • Esailija
    Esailija over 12 years
    Try console.log( Object.keys( that.data[0].cards ) );. If that doesn't work try console.log( that.data[0].cards.propertyIsEnumerable("E") ); If that doesn't work try console.log( that.data[0].cards.__lookupGetter__( "E" ) ); If THAT doesn't work just link to the page :D
  • maxedison
    maxedison over 12 years
    I've updated my post to show the result of that. I can't link to the page because I'm doing the development locally. This is easily one of the weirdest things I've ever encountered in programming...
  • Esailija
    Esailija over 12 years
    How are you creating the object, where does it come from? Have you isolated it on a clean page?
  • maxedison
    maxedison over 12 years
    The object gets created dynamically via AJAX requests that load XML data (using jQuery). Once all the data is loaded, it is parsed (again, using jQuery). It's at this point that the supposedly "undefined" arrays (cards.E, cards.N, card.X) are created. I'll try your latest edit in the morning. Thanks for your help.
  • rr-
    rr- almost 10 years
    I stumbled into the same problem today. Thanks.