问题
I have an object with arrays as values.
people = {
'steve':['foo','bar'],
'joe':['baz','boo']
}
For each key, I would like to loop over the values in the corresponding array. Simple enough:
for ( var person in people ) {
person.forEach( function(item) {
console.log(item)
})
}
But JSHint complains:
Don't make functions within a loop.
Is this truly an issue with my code? I quite like the short ES5 for loop syntax. Do I need to use the ES3 style or change my code in some other way?
回答1:
There are two issues there, the one that JSHint is warning you about, and a more fundamental one.
The thing that JSHint is warning you about is that in theory, every time that loop runs, a new function is created. This would be better:
for ( var person in people ) {
person.forEach(handlePerson);
}
function handlePerson(item) {
console.log(item)
}
I say "in theory" because although the spec requires that a new function object be created each time, that doesn't mean engines can't reuse the underlying implementation of the function, and it doesn't mean that engines can't reuse the same function object if you didn't assign any other properties to it or keep a reference to it. I asked the V8 guys about it (V8 being the JavaScript engine in Chrome), and they said that Chrome will "...in most cases..." reuse the underlying function implementation for different function objects created at the same point in the source code, and that they would "expect" that most other engines would do the same.
So JSHint may be being a bit over-the-top in this particular case. But it's frequently a useful warning, particularly if the functions you're creating inside the loop refer to variables whose contents change during the loop, which is the classic closure error people make.
But more fundamentally, person
is a String
(it's the name of a property in people
), and String
doesn't have forEach
. You wanted:
for ( var person in people ) {
people[person].forEach(handlePerson);
}
function handlePerson(item) {
console.log(item)
}
...e.g., people[person]
to get the array for that key.
回答2:
In addition to other commenters, if you know what you are doing, you can disable this warning with JSHint option loopfunc
:
/*jshint loopfunc:true */
for ( var person in people ) {
person.forEach( function(item) {
console.log(item)
})
}
You can set JSHint options globally (if you're using NPM module), per-file or per-function.
回答3:
You're allowed to use forEach
inside the loop, but you're not allowed to declare a function inside a loop.
function looper (item) {
console.log(item)
}
for ( var person in people ) {
person.forEach(looper)
}
... otherwise you're recreating the same function for each iteration.
回答4:
It’s not the forEach, it’s the anonymous function that it’s complaining about.
回答5:
The reason this is a problem is that it create a new object reference to the anonymous function inside the foreach
call in the Heap every time you do this. It would be better if you assigned the function to a variable outside of the for loop, that way you're not eating up memory needlessly
来源:https://stackoverflow.com/questions/10451865/jshint-wont-let-me-use-foreach-in-a-for-loop