Lodash forOwn 和 forOwnRight 迭代顺序

Lodash forOwn and forOwnRight iteration order

在lodash中你可以找到以下函数:

_.forOwn _.forOwnRight

forOwn 函数的示例按 a-z 顺序迭代属性,但表示:

iteration order is not guaranteed

虽然 forOwnRight 声称以相反的 (z-a) 顺序迭代。

这对我来说意义不大,所以有2个问题

  1. 如果不能保证迭代顺序,为什么还要存在 forOwnRight
  2. 为什么不能保证订单?
  1. 不能保证顺序,但顺序是一致的。这意味着 _.forOwnRight 保证提供与 _.forOwn

  2. 相反的结果
  3. 这是按照规范:它没有说明对象的属性必须如何排序,所以这取决于 JS 引擎如何处理它(出于性能原因,它们的处理方式有所不同)。

注意:顺序不仅取决于特定的 ES 实现,还取决于运行时,因为现代 JS 虚拟机在运行时会进行大量试探。

对于那些对优化感兴趣的人来说,这里是一个很好的 link(它严重不适合在此 Q/A 中涵盖):

查看源代码我们可以看到:

function baseForOwn(object, iteratee) {
    return baseFor(object, iteratee, keys);
}

function baseForOwnRight(object, iteratee) {
    return baseForRight(object, iteratee, keys);
}

function baseFor(object, iteratee, keysFunc) {
    var index = -1,
        iterable = toObject(object),
        props = keysFunc(object),
        length = props.length;
    while (++index < length) {
        var key = props[index];
        if (iteratee(iterable[key], key, iterable) === false) {
            break;
        }
    }
    return object;
}

function baseForRight(object, iteratee, keysFunc) {
    var iterable = toObject(object),
        props = keysFunc(object),
        length = props.length;
    while (length--) {
        var key = props[length];
        if (iteratee(iterable[key], key, iterable) === false) {
            break;
        }
    }
    return object;
}

这两个函数在内部都依赖于 keysFunc,其中 returns 是传递对象的键。由于对象的键的顺序没有严格定义,无法事先知道顺序,但是两种方法内部使用相同的方法,所以颠倒的顺序保证是完全颠倒的。

我觉得先回答问题2比较容易

  1. 函数 forOwnforOwnRight 都与对象一起工作,因此,不能保证属性的顺序,如 4.3.3 对象 中所述Ecma-262 specification 的:

[An object] is an unordered collection of properties each of which contains a primitive value, object, or function.

通常这些属性是由 VM 按插入顺序打印的,但这不应被视为普遍事实。另请参阅 this question 以获取更多详细信息。

  1. 不过,假设 forOwn 在特定 javascript 运行时 上按以下顺序处理属性 [a, c, b] ,您可以保证forOwnRight 将按 [b, c, a] 的顺序处理属性。因此,两种方法都有用。