【问题标题】:JSHint won't let me use 'forEach' in a 'for' loopJSHint 不允许我在“for”循环中使用“forEach”
【发布时间】:2012-05-14 04:15:19
【问题描述】:

我有一个以数组为值的对象。

people = {
    'steve':['foo','bar'],
    'joe':['baz','boo']
}

对于每个键,我想循环遍历相应数组中的值。很简单:

for ( var person in people ) {
    person.forEach( function(item) {
      console.log(item)
    })
}

但是 JSHint 抱怨:

Don't make functions within a loop.

这真的是我的代码的问题吗?我非常喜欢简短的 ES5 for 循环语法。我是否需要使用 ES3 样式或以其他方式更改我的代码?

【问题讨论】:

    标签: javascript ecmascript-5 jshint


    【解决方案1】:

    这里有两个问题,一个是 JSHint 警告您的问题,另一个是更根本的问题。

    JSHint 警告您的是,理论上,每次循环运行时,都会创建一个新函数。这样会更好:

    for ( var person in people ) {
        person.forEach(handlePerson);
    }
    function handlePerson(item) {
      console.log(item)
    }
    

    我说“理论上”是因为虽然规范要求每次都创建一个新函数object,但这并不意味着引擎不能重用底层实现 函数,这并不意味着如果您没有为它分配任何其他属性或保留对它的引用,引擎就不能重用相同的函数对象。我asked the V8 guys about it(V8 是 Chrome 中的 JavaScript 引擎),他们说 Chrome 将“……在大多数情况下……”为源代码中同一点创建的不同函数对象重用底层函数实现,并且他们会“期望”大多数其他引擎也会这样做。

    所以在这种特殊情况下,JSHint 可能有点过头了。但这通常是一个有用的警告,特别是如果您在循环中创建的函数引用了在循环期间内容发生变化的变量,这是人们犯的经典闭包错误。

    但更根本的是,personString(它是people 中的属性名称),而String 没有forEach。你想要的:

    for ( var person in people ) {
        people[person].forEach(handlePerson);
    }
    function handlePerson(item) {
      console.log(item)
    }
    

    ...例如,people[person] 以获取该键的数组。

    【讨论】:

    • 我猜他的意思是people[person].forEach(...)。不管怎样,这个警告对于现代 JS 引擎来说似乎很愚蠢——它们很可能不会为每次迭代创建一个新函数。
    • @Rocket:天哪,问题就在这里。 叹息谢谢。
    • 在循环中使用匿名函数时似乎仍然会对性能产生一些影响。 jsperf.com/anon-vs-named-in-loop
    • @user1370958:我敢打赌它与内联和/或创建对象包装器有关。非常有用的数据。顺便说一句,请注意,这不是命名函数和匿名函数之间的区别,而是在循环中创建函数与否之间的区别。循环中的函数可以有名称(使用命名函数表达式),而未在循环中创建的函数可以是匿名的(分配给变量)。
    【解决方案2】:

    除了其他评论者,如果你知道自己在做什么,你可以使用 JSHint 选项 loopfunc 禁用此警告:

    /*jshint loopfunc:true */
    
    for ( var person in people ) {
      person.forEach( function(item) {
        console.log(item)
      })
    }
    

    您可以全局设置 JSHint 选项(如果您使用 NPM 模块)、每个文件或每个函数。

    【讨论】:

    • 在 2016 年读到这篇文章:我非常知道我在做什么。 PS。嗨安东!
    【解决方案3】:

    你可以在循环内使用forEach,但你不能在循环内声明函数。

    function looper (item) {
      console.log(item)
    }
    
    for ( var person in people ) {
        person.forEach(looper)
    }
    

    ...否则,您将为每次迭代重新创建相同的函数。

    【讨论】:

      【解决方案4】:

      它抱怨的不是 forEach,而是匿名函数。

      【讨论】:

        【解决方案5】:

        这是一个问题的原因是,每次执行此操作时,它都会在堆中的 foreach 调用中创建一个对匿名函数的新对象引用。如果您将函数分配给 for 循环之外的变量会更好,这样您就不会不必要地消耗内存

        【讨论】:

          猜你喜欢
          • 2015-01-21
          • 2021-03-22
          • 2015-09-17
          • 2018-01-16
          • 2014-05-31
          • 1970-01-01
          • 2018-07-16
          • 1970-01-01
          • 2012-01-27
          相关资源
          最近更新 更多