3

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

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

基本流程:

  1. 对象已初始化(非常底部)
  2. 它称为“负载”
  3. 当 ajax 在加载中返回时,data.objects 包含一个 json 对象数组。该数组上没有未定义的条目。
  4. setObjects 被调用,所有来自 ajax 调用的对象都被复制到 this.objects。
  5. 当它们被复制时,我可以看到未定义的条目出现在萤火虫中,如果我没有第二次传递数组并拼接出未定义的条目,它会在尝试访问模板中的数组元素时破坏胡子。

为什么 javascript 会自动用未定义的条目填充 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( );
4

2 回答 2

5

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

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

关键是您正在设置这样的数组条目:

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

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

标准的 JavaScript 数组根本不是一个真正的数组(除非经过 JavaScript 引擎优化),它是一个对一些事情进行特殊处理的对象。

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

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 对象所做的那样(因为数组“元素”实际上是对象属性,而数组“索引”实际上是属性名称)。

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

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

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

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

this.objects.push(objects[ i ]);
于 2013-02-28T08:26:45.020 回答
2

当你这样做时

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

您要求数组扩展this.objectsobjects[ i ].id. undefined当您需要未填充索引处的元素时,引擎没有其他解决方案。

如果您的数组大部分为空(稀疏数组),您可能应该使用对象作为映射,即使用

this.objects = {};
于 2013-02-28T08:21:56.530 回答