Reputation: 1031
I got a FileHelper-method that lists the name of all files and eventually returns the filenames:
import fs from 'fs';
import path from 'path';
class FileHelper {
static ListFiles() {
const fileDir = `${path.resolve()}/Specifications/`;
let files = fs.readdirSync(fileDir);
for (const file in files) {
console.log(file); // Prints filename correctly: 'petstore.json'
}
return files;
}
}
export default FileHelper;
However, when I invoke this method and print it once again in a for-loop it prints the array index and not the value:
import FileHelper from './Helpers/FileHelper.js';
function main() {
try {
let specifications = FileHelper.ListFiles();
for (const specification in specifications) {
console.log(specification); // prints '0' instead of 'petstore.json'
}
}
catch(err) {
console.error(err);
}
}
main();
Why does it not print the file name in the second for-loop? Thanks!
Upvotes: 2
Views: 1662
Reputation: 3526
The reason you're seeing the key is because the for...in
loop iterates over the keys of an array.
function main() {
try {
let specifications = FileHelper.ListFiles();
for (const key in specifications) {
const { [key]: value }= specifications;
// ^ the above line is equivalent to
// const value = specifications[key]
console.log(key, value);
}
}
catch(err) {
console.error(err);
}
}
Check out the MDN documentation on for...in
, which explains:
The for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.
In the comments to your question, Arun linked to an excellent StackOverflow question that explains different ways of accomplishing your goal: why is using for...in for array iteration a bad idea
One of those alternative ways is for...of
, which looks:
for (const specification of specifications) {
console.log(specification);
}
The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables. It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object.
Also, you can ierate over the array using Array.prototype.forEach()
. Here's that approach:
specifications
.forEach((currentKey) => {
const { [currentKey]: specificationValue } = specifications;
console.log(currentKey, specificationValue);
})
Or you can do it the old fashioned way -- with a for
loop:
for (let i = 0; i < specifications.length; i++) {
console.log(i, specifications[i])
}
Upvotes: 3