Lodash forOwn 和 forOwnRight 迭代顺序
Lodash forOwn and forOwnRight iteration order
在lodash中你可以找到以下函数:
forOwn
函数的示例按 a-z 顺序迭代属性,但表示:
iteration order is not guaranteed
虽然 forOwnRight
声称以相反的 (z-a) 顺序迭代。
这对我来说意义不大,所以有2个问题
- 如果不能保证迭代顺序,为什么还要存在
forOwnRight
?
- 为什么不能保证订单?
不能保证顺序,但顺序是一致的。这意味着 _.forOwnRight
保证提供与 _.forOwn
相反的结果
这是按照规范:它没有说明对象的属性必须如何排序,所以这取决于 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比较容易
- 函数
forOwn
和 forOwnRight
都与对象一起工作,因此,不能保证属性的顺序,如 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 以获取更多详细信息。
- 不过,假设
forOwn
在特定 javascript 运行时 上按以下顺序处理属性 [a, c, b]
,您可以保证forOwnRight
将按 [b, c, a]
的顺序处理属性。因此,两种方法都有用。
在lodash中你可以找到以下函数:
forOwn
函数的示例按 a-z 顺序迭代属性,但表示:
iteration order is not guaranteed
虽然 forOwnRight
声称以相反的 (z-a) 顺序迭代。
这对我来说意义不大,所以有2个问题
- 如果不能保证迭代顺序,为什么还要存在
forOwnRight
? - 为什么不能保证订单?
不能保证顺序,但顺序是一致的。这意味着
_.forOwnRight
保证提供与_.forOwn
相反的结果
这是按照规范:它没有说明对象的属性必须如何排序,所以这取决于 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比较容易
- 函数
forOwn
和forOwnRight
都与对象一起工作,因此,不能保证属性的顺序,如 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 以获取更多详细信息。
- 不过,假设
forOwn
在特定 javascript 运行时 上按以下顺序处理属性[a, c, b]
,您可以保证forOwnRight
将按[b, c, a]
的顺序处理属性。因此,两种方法都有用。