为什么新的javascript数组有'undefined'条目?

时间:2013-02-28 08:19:27

标签: javascript undefined

这是一个演示数组的示例,当您填充它时,它也会获取所有类型的未定义条目。

这是在firefox 19.0 / firebug上,不确定它是否在其他浏览器上发生。

基本流程:

  1. 对象已初始化(非常底部)
  2. 称之为“加载”
  3. 当ajax在load中返回时,data.objects包含一个json对象数组。该数组上没有未定义的条目。
  4. 调用setObjects,将来自ajax调用的所有对象复制到this.objects。
  5. 当它们被复制时,我可以看到 undefined 条目显示在firebug中,如果我没有再次传递数组并拼接出未定义的条目,它会在尝试访问元素时断开小胡子模板中的数组。
  6. 为什么javascript会自动使用 undefined 条目填充this.objects数组?

    以下是代码:

    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( );
    

2 个答案:

答案 0 :(得分:3)

  

为什么javascript会自动填充带有未定义条目的this.objects数组?

它没有,但它可以看起来那样。

关键是你要设置这样的数组条目:

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

......显然,objects[ i ].id有时会高于数组中的条目数。

标准的JavaScript数组isn't really an array at all,它是一个对某些东西进行特殊处理的对象。

让我们举一个更简单的例子:

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

如您所见,如果您写入超出数组末尾的数组条目,则数组的length将调整为比您写入的索引高一个。

但JavaScript并没有用undefined“填充”数组。 a[0]a[1]a[2] 的条目不存在

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

但是如果你向一个数组询问一个不存在的条目,你会得到undefined

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

...当您要求不存在的属性时,就像从任何其他JavaScript对象那样做(因为数组“元素”实际上是对象属性,而数组“索引”实际上是属性名称)。

与实际存在的值undefined的条目不同,这也是可能的:

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

所以Mustache正在从0length - 1循环遍历数组并询问条目,其中一些条目不存在,导致undefined

这是一个很长的说法,您可能希望将该行更改为:

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

答案 1 :(得分:2)

当你这样做时

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

您要求数组将this.objects扩展到objects[ i ].id。当您需要未填充索引处的元素时,没有其他解决方案可以为您提供undefined

如果你的数组大部分是空的(一个稀疏数组),你可能应该使用一个对象作为map,用

初始化它
this.objects = {};