【问题标题】:javascript push inside init method not updating array length correctlyjavascript push inside init 方法没有正确更新数组长度
【发布时间】:2014-06-17 11:12:16
【问题描述】:

我正在尝试使用 init 方法创建一个对象数组,当我将一个对象推入数组时,它应该将另一个对象推入数组,同时跟踪数组的长度。问题就是在所有对象都添加完之后才更新数组的长度,所以当每个对象试图去抓取长度的时候,都得到0。 我怎样才能让它在这个过程中更新长度? 这是 jfiddle:http://jsfiddle.net/bg3Vg/13/ 如您所见,它给出了一条消息,显示 grouptotal 为 5,但似乎总数从最后一个推送的对象到第一个.. 我需要它以正确的顺序工作,以便最后一个推送的对象可以检索正确的长度。

var colorGroup = [];
var grouptotal = 0;

colorGroup.push(new groupdata(0) );
alert(grouptotal+","+colorGroup[colorGroup.length-1].parent);

function groupdata(parent) {
    this.parent = parent;
    this.refnum;

    this.init =  function() 
    {
        grouptotal++;
        this.refnum = colorGroup.length;
        if(grouptotal<5)colorGroup.push(new groupdata( this.refnum ) );
    }
    this.init();

}

编辑: 好的,我找到了解决我的问题的方法。让我知道这个解决方案有多可怕..http://jsfiddle.net/EqAqv/1/

var colorGroup = [];
var grouptotal = 0;

var colorGroupWait = [];

colorGroup.push(new groupdata(0) );

while(colorGroupWait.length>0){
    var newcolorGroup = colorGroupWait.shift();

    colorGroup.push(new groupdata(newcolorGroup) );
}

alert(grouptotal+","+colorGroup[colorGroup.length-1].parent);  
alert(grouptotal+","+colorGroup[colorGroup.length-2].parent); 

function groupdata(parent) {
    this.parent = parent;
    this.refnum;

    this.init =  function() 
    {
        grouptotal++;
        this.refnum = colorGroup.length;
         if(colorGroup.length<5)colorGroupWait.unshift( this.refnum );
    }
    this.init();

}

【问题讨论】:

  • 你为什么尝试通过他们的refnum 引用groupdata 实例而不是简单地通过对象引用?
  • 我不确定我是否理解您的问题。我试图计算有多少对象被设置为推送,以便它们引用数组中的正确 id。虽然我不能使用 for 循环..
  • 不,我想问你需要什么refnum?例如,将实例传递为 parent 而不是某个数字会更容易。

标签: javascript arrays push init


【解决方案1】:

JavaScript 数组 do 在您向其推送内容时立即更新 length 属性。问题是您递归地调用构造函数,因此语句this.refnum = colorGroup.length 将在每次初始化之前执行任何推送。

换句话说,JavaScript 正在按预期工作。

您以这种令人费解的方式这样做有什么特别的原因吗?如果您这样做会更直接(并获得您想要的结果):

for(grouptotal=0; grouptotal<5; grouptotal++){
    colorGroup.push( new groupdata(grouptotal) );
}

此外,JavaScript 中的惯例是用大写字母命名对象构造函数。因此,虽然groupdata 不是无效语法,但它令人困惑:您应该考虑将其命名为Groupdata

【讨论】:

  • 我需要按我发布的方式使用它,因为它可能会为每个新添加将多个推入数组中。我简化了问题,但我的情况更复杂。所以说,我添加一个..它发现它必须添加 4.. 然后对于每一个,他们根据每个人的决定添加另一个,等等等等。我不能使用 for 循环,因为每个加法需要参考以前的加法,但在它发生之前我无法说出它们引用的内容。如果我保留一个值并增加它,据我所知,它不会与其他所有内容保持同步..
  • 如果逻辑(“发现它需要......”)需要在构造函数中,那么您不应该添加它。相反,将所有关于refnumscolorGroups(以及其他)的逻辑放入构造函数,然后告诉它 来创建一些东西。您不需要自己将项目推送到数组中。
  • 是的,我同意@Bergi。总的来说,对象构造器应该遵循自我关注的原则:他们应该只负责初始化一个single对象的属性。如果构造函数需要构造其他对象,那么这表明您需要它之外的东西来管理这些关系。如果您需要对象具有唯一的 ID,那么使用 UUID 或递增整数很容易。
【解决方案2】:

@EthanBrown 已经指出了问题所在。这是一个将所有逻辑都放在构造函数中的解决方案,避免了在创建实例后从错误的编号推送实例的问题。

function GroupData(parentnum) {
    this.parentnum = parentnum;

    this.refnum = GroupData.colorGroup.length;
    GroupData.colorGroup.push(this);

    if (GroupData.colorGroup.length < 5)
        new GroupData(this.refnum);
}
GroupData.colorGroup = [];

var root = new GroupData(0);
alert(GroupData.colorGroup.length+", "
     +GroupData.colorGroup[GroupData.colorGroup.length-1].parentnum);

【讨论】:

  • 这很有趣.. 我很难让自己的思想适应它的结构方式。我编辑了我的原始帖子以展示我自己制作的解决方案。你可以告诉我这是否是不好的做法。不过我会尝试理解你的解决方案。
  • 它只是在构造函数中移动了push,使init不是立即执行的方法,而只是放置代码,将数组放在GroupData“命名空间”中逻辑上属于那里,并删除了 grouptotal 的东西,它不过是数组长度的一个不起眼的别名。
  • 是的,您的解决方案仍然很糟糕,甚至比第一次尝试还要糟糕。人们不明白colorGroupWait 应该包含什么,它是如何被填充的(似乎发生在两个地方?)以及为什么它又被清空了。它属于哪里?它是 groupData 内部的,还是仅仅是创建 5 个实例的代码的助手?两者兼而有之,这就是问题所在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多