Javascript Lodash forOwn和forOwnRight迭代顺序

Javascript Lodash forOwn和forOwnRight迭代顺序,javascript,lodash,Javascript,Lodash,在lodash中,您可以找到以下功能: 例如,forOwn函数按a-z顺序迭代属性,但表示: 迭代顺序不能保证 而forOwnRight声称正在以相反的(z-a)顺序进行迭代 这对我来说没有多大意义,所以有两个问题 如果没有对迭代顺序的保证,forOwnRight为什么会存在 为什么订单不能保证 订单不保证,但保持一致。这意味着.forOwnRight保证提供与.forOwn相反的结果 它符合规范:它没有说明对象的属性必须如何排序,所以由JS引擎如何处理它(出于性能原因,它们的处理方式有所不

在lodash中,您可以找到以下功能:

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

迭代顺序不能保证

forOwnRight
声称正在以相反的(z-a)顺序进行迭代

这对我来说没有多大意义,所以有两个问题

  • 如果没有对迭代顺序的保证,
    forOwnRight
    为什么会存在
  • 为什么订单不能保证
  • 订单不保证,但保持一致。这意味着
    .forOwnRight
    保证提供与
    .forOwn
    相反的结果

  • 它符合规范:它没有说明对象的属性必须如何排序,所以由JS引擎如何处理它(出于性能原因,它们的处理方式有所不同)

  • 注意:顺序不仅取决于特定的ES实现,还取决于运行时,因为现代JS虚拟机在运行时执行很多启发式操作

    对于那些对优化感兴趣的人来说,这里有一个很好的链接(它严重不适合在本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;
    }
    
    函数baseForOwn(对象,迭代对象){
    返回baseFor(对象、迭代对象、键);
    }
    函数baseForOwnRight(对象,迭代对象){
    返回baseForRight(对象、迭代对象、键);
    }
    函数baseFor(对象、迭代对象、keysFunc){
    var指数=-1,
    iterable=toObject(对象),
    props=keysFunc(对象),
    长度=道具长度;
    而(++索引<长度){
    var键=道具[索引];
    if(iteratee(iterable[key],key,iterable)==false){
    打破
    }
    }
    返回对象;
    }
    函数baseForRight(对象、迭代对象、keysFunc){
    变量iterable=toObject(对象),
    props=keysFunc(对象),
    长度=道具长度;
    while(长度--){
    变量键=道具[长度];
    if(iteratee(iterable[key],key,iterable)==false){
    打破
    }
    }
    返回对象;
    }
    

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

    我认为先回答问题2比较容易

  • 两个函数
    forOwn
    forOwnRight
    都与对象一起工作,因此,不保证属性的顺序,如以下文件的4.3.3对象中所述:
  • [对象]是一个无序的属性集合,每个属性 包含基元值、对象或函数

    通常,属性由VM按插入顺序打印,但这不应视为一般事实。有关更多详细信息,请参阅

  • 尽管如此,假设
    forOwn
    在特定javascript运行时按以下顺序处理属性
    [a,c,b]
    ,您可以保证
    forOwnRight
    将按
    [b,c,a]
    的顺序处理属性。因此,两种方法都有意义

  • 你能举例说明订单什么时候会改变吗?这些实现有何不同?什么样的优化会导致订单发生变化?@RobertRossmann在V8内部添加了一个链接来解释这一点。