【问题标题】:Function call as iterable in for of loop ES6函数调用作为循环 ES6 中的可迭代
【发布时间】:2017-09-18 08:17:13
【问题描述】:

寻找最佳实践建议。

for of中的函数调用作为可迭代对象是一种好习惯吗?

const obj = {key1:'a', key2:'b'};

for(const i of Object.keys(obj)){ ... }

最好有

const obj = {key1:'a', key2:'b'};
const allKeys = Object.keys(obj);
for(const i of allKeys){ ... }

不是在循环的每次迭代中调用 Object.keys 函数吗?

【问题讨论】:

  • 它们是等价的

标签: javascript object ecmascript-6


【解决方案1】:

你可以通过模拟一个类似的案例来检查它

function A(){
    console.log('function called');
    return [1, 2, 3, 4, 5];
}

for(let i of A()){
    console.log(i);
}

如你所见,A() 只被调用一次

【讨论】:

  • 可以,当然,但最好了解实际发生的情况。
【解决方案2】:

您的第一个示例与第二个示例执行相同的操作,只是没有allKeys 常量。在您的第一个示例中:

const obj = {key1:'a', key2:'b'};

for(const i of Object.keys(obj)){ ... 

...Object.keys 只会被调用一次,然后它的迭代器将被检索并用于循环。 (这在规范中的ForIn/OfHeadEvaluation 中有介绍,但它...很繁重。)所以你可以使用这种形式,它并不是低效的。

【讨论】:

    【解决方案3】:

    Object.keys 的调用在两种变体中只调用一次。

    但也可以考虑这个不依赖于Object.keysfor 循环:

    for (const prop in obj) {  } 
    

    Object.keys 创建一个数组,而上面的for 循环没有。后者仅在必要时检索项目。当然,如果您的 for 循环从未过早退出,它仍会检索所有这些,因此只有在您计划过早退出循环时才会有所不同。在这种情况下,相应的迭代器永远不会访问剩余的项目,而Object.keys 在创建数组时已经这样做了。

    需要注意的一点:for .. in 循环还会迭代可枚举的inherited 属性,而不仅仅是拥有 属性,而Object.keys 只会列出拥有可枚举的属性。您可以在for 循环中添加额外的测试以排除非自己的属性:

    if (obj.hasOwnProperty(prop))
    

    【讨论】:

    • 当然应该是in,而不是of。感谢您的提及,@T.J.Crowder。
    • 啊....当然。出于某种原因,我没有这样做。我建议调用不同的继承属性。
    • 我很好奇你的断言“上面的for 循环没有[创建一个数组]”,并且“只在必要时检索项目”。当然它不会创建一个实际的数组,但我怀疑大多数或所有引擎都会准备一个所有键的内部列表——不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多