Why does a new javascript array have 'undefined' entries?

懵懂的女人 提交于 2021-02-07 20:12:21

问题


Here's a sample that demonstrates an array that as you fill it in, it gets all types of undefined entries in it as well.

This is on firefox 19.0/firebug, not sure if it happens on other browsers.

Basic flow:

  1. Object is initialized (very bottom)
  2. It calls "load"
  3. When the ajax returns in load, data.objects contains an array of json objects. This array has no undefined entries on it.
  4. setObjects gets called where all the objects from the ajax call are copied to this.objects.
  5. As they are copied I can see undefined entries show up in firebug, If I didn't pass the array a second time and splice out the undefined entries it breaks mustache when trying to access the elements of the array in a template.

Why does javascript automatically pad out the this.objects array with undefined entries?

Here's the code:

function MailerFromProfile( )
{
    // privileged
    this.objects = [];
    this.load( );
}

MailerFromProfile.prototype.setObjects = function( objects )
{
    for( var i in objects )
    {
        if( 'undefined' !== objects[ i ] )
        {
            this.objects[ objects[ i ].id ] = objects[ i ];
        }
    }
    // I should not have to do this:
    for( var i = 0; i < this.objects.length; i++ )
    {
        if( typeof this.objects[ i ] === 'undefined' )
        {
            this.objects.splice( i, 1 );
            i--;
        }
    }
}

MailerFromProfile.prototype.setTemplate = function( n, v )
{
    this.template[ n ] = v;
}

MailerFromProfile.prototype.load = function( )
{
    jQuery.post(
        MAILER_PATH,
        { session: MAILER_SESSION,
          object : 'from_profile',
          action : 'list'
        },
        function( data )
        {
            if( typeof data.objects !== 'undefined' )
            {
                g_mailer_from_profiles.setObjects( data.objects );
            }
        },
        'json' );
}

var g_mailer_from_profiles = new MailerFromProfile( );

回答1:


When you do this

this.objects[ objects[ i ].id ] = objects[ i ];

you ask for the array to extend this.objects up to objects[ i ].id. There is no other solution for the engine than to give you undefined when you require the element at an unfilled index.

If your array is mostly empty (a sparse array), you should probably use an object as map instead, that is initialize it with

this.objects = {};



回答2:


Why does javascript automatically pad out the this.objects array with undefined entries?

It doesn't, but it can look that way.

The key bit is that you're setting array entries like this:

this.objects[ objects[ i ].id ] = objects[ i ];

...and so apparently, objects[ i ].id is sometimes higher than the number of entries in the array.

The standard JavaScript array isn't really an array at all (unless optimized by the JavaScript engine), it's an object with special handling of a couple of things.

Let's take a simpler example:

var a = [];            // An empty array
console.log(a.length); // 0
a[3] = "foo";          // Puts an entry at index 3
console.log(a.length); // 4

As you can see, if you write to an array entry that's beyond the end of the array, the length of the array is adjusted to be one higher than the index you wrote to.

But JavaScript doesn't "pad out" the array with undefined. The entries at a[0], a[1], and a[2] don't exist:

console.log(1 in a);   // false

But if you ask an array for an entry that doesn't exist, you get undefined:

console.log(a[1]);     // undefined

...just like you do from any other JavaScript object when you ask for a property that doesn't exist (because array "elements" are actually object properties, and array "indexes" are actually property names).

That's different from an entry actually existing there with the value undefined, which is also possible:

a[1] = undefined;
console.log(1 in a);   // true
console.log(a[1]);     // undefined

So Mustache is looping through the array from 0 to length - 1 and asking for the entries, some of which don't exist, resulting in undefined.

Which is a long way of saying, you may want to change that line to:

this.objects.push(objects[ i ]);


来源:https://stackoverflow.com/questions/15130654/why-does-a-new-javascript-array-have-undefined-entries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!