这是一个演示数组的示例,当您填充它时,它也会获取所有类型的未定义条目。
这是在firefox 19.0 / firebug上,不确定它是否在其他浏览器上发生。
基本流程:
为什么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( );
答案 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正在从0
到length - 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 = {};