如何在JavaScript中迭代一组对象?

时间:2010-06-25 06:31:42

标签: javascript json object

我正在使用PHP从我的数据库中获取“任务”并将其编码为JSON。当我将数据传输到javascript时,我最终会得到类似的结果:

Array {
   [0] => Task {
      id: 2,
      name: 'Random Task',
      completed: 0
   }
   [1] => Task {
      id: 8,
      name: 'Another task',
      completed: 1
   }
}

我想我真正的问题是,通过id找到任务的最有效方法是什么?迭代数组并检查每个对象似乎可能不是最有效的?还有其他办法吗?

6 个答案:

答案 0 :(得分:6)

关于Javascript对象的事情是它们是必不可少的地图。您可以通过使用点表示法(“object.property”)和索引表示法(“object [”property“])来访问属性。您还可以通过其属性枚举,使用for(i ...)或for (在...)

for (var i = 0; i < arrayObj.length; i++) { ... }

for (var prop in arrayObj) { ... }

我最近一直在做的是为数组对象构建一些Linq-esque扩展:

Array.prototype.Where = function(predicate) {
    Throw.IfArgumentNull(predicate, "predicate");
    Throw.IfNotAFunction(predicate, "predicate");

    var results = new Array();
    for (var i = 0; i < this.length; i++) {
        var item = this[i];
        if (predicate(item))
            results.push(item);
    }

    return results;
};

忽略我的自定义Throw类型,它基本上允许你做类似的事情:

var item = arrayObj.Where(function(i) { return (i.id == 8); }).FirstOrDefault();

如果您有兴趣,我会在某个时候发布所有内容吗?

答案 1 :(得分:2)

通常,在Javascript中迭代数组集合的最有效方法是坚持本机for循环。我说“通常”的原因是实现归结为每个独特浏览器的javascript实现,因此没有绝对明确的答案。

http://solutoire.com/2007/02/02/efficient-looping-in-javascript/有一篇很好的文章,它涵盖了每种主要迭代方法的表现,并且在经验上得出了相同的结论。

答案 2 :(得分:2)

如果您不需要维护顺序,那么最好的方法是使用常规对象,并按任务ID进行索引。这样就可以O(1)访问。

var tasks = {
   '2': {
      id: 2,
      name: 'Random Task',
      completed: 0
   },
   ...
}

如果您还需要维护订购,则编写一个OrderedMap“类”,通过创建任务ID数组来维护订单,但实际任务仍将存储在由任务ID索引的对象中。所以基本上你会有:

// internal API (to help maintain order)
taskIDs = [a, b, c, ..];
// internal API (for actual storage)
tasks = {
    a: { .. },
    b: { .. },
};

// external API for iterating objects in order
forEach(fn);
// external API for accessing task by ID
get(id);

只要你提供了一个很好的封装方式来按顺序迭代这些,并通过任务ID访问它们,外面世界可能不知道你如何维护秩序。

如果您需要参考来实现此类,请参阅Google Closure Library中的source LinkedMap

答案 3 :(得分:2)

再多一点思考,这就是我最终的目标:

this.find = function (test) {
    var results = [];
    for (var i = 0,l = this.tasks.length; i < l; i++) {
        var t = this.tasks[i];
        if (eval(test)) {
            results.push(this.tasks[i]);
        }
    }
    return results;
}

这允许我做一个简单的tasks.find('t.id == 2')或tasks.find('t.completed == 1');

答案 4 :(得分:0)

如果id是唯一的(并且大部分是连续的),您可以对数组进行一次重新排列,以便数组索引反映id。如果它们不是唯一的,您可以对它们进行排序并进行二分查找。

但是只有当你经常通过数组中的id访问项目时这才有用,否则排序的开销将不值得。

答案 5 :(得分:0)

你的阵列是否很大?如果没有,你可能不会在优化它时赢得很多微秒。

如果它很大,你应该真正返回一个字典(如Matthew Flaschen评论),它使用任务的ID作为键。通过这种方式,您将获得恒定的时间查找(至少如果javascript实现是最佳的)。

只需使用普通的PHP关联数组,并通过json_encode或您正在使用的任何内容运行它。

//Assume you have your original Array named $tasks:
$dictionary = Array();
foreach($tasks as $task)
    $dictionary[$task->getID()] = $task;