12

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

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 样式或以其他方式更改我的代码?

4

5 回答 5

21

那里有两个问题,一个是 JSHint 警告你的,一个是更根本的问题。

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

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

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

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

但更根本的是,person是 a String(它是 中的属性名称people),并且String没有forEach. 你自找的:

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

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

于 2012-05-04T15:35:53.943 回答
9

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

/*jshint loopfunc:true */

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

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

于 2012-05-04T17:38:29.033 回答
1

您可以forEach在循环内使用,但不允许在循环内声明函数。

function looper (item) {
  console.log(item)
}

for ( var person in people ) {
    person.forEach(looper)
}

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

于 2012-05-04T15:35:41.870 回答
0

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

于 2012-05-04T15:36:01.870 回答
0

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

于 2012-05-04T15:36:02.260 回答