Reputation: 315
I understand there is a lot of documentation and courses on callbacks. I have read a number of those resources, but for this particular problem I don't understand what is going on. And, I think help with this particular problem will help me understand callbacks better.
In short I do not understand why I can access 'ext' in a part of the main 'readFile()' function, but I can't pass it into functions within that function, ie the 'filterData()' function.
Thanks for your help in understanding this.
const fs = require("fs");
const path = require("path");
const dir1 = process.argv[2];
const fileType = process.argv[3];
const whenDone = function(err, data) {
if(err) {
console.log(err);
} else {
for(i = 0; i < data.length - 1; i++) {
console.log(data[i]);
}
}
}
let arr = [];
function readFile(dirName, ext, callback) {
fs.readdir(dirName, function (err, data) {
if (err) {
return callback(err, null);
}
// ext and data are defined here:
console.log(ext, data);
function filterData(ext) {
// ext and data are not defined here?
console.log(ext, data);
return data.filter(function(files) {
return arr = files.includes(ext);
console.log(arr);
});
return callback(null, arr);
}
});
}
readFile(dir1, fileType, whenDone);
Upvotes: 1
Views: 636
Reputation: 65806
The reason is that in the nested function (filterData
), you declare an argument (essentially a local variable) with the same name (ext
) that already exists in the higher scope (readFile
), so, for the duration of the filterData
function, ext
refers to what is passed to it, not the ext
that was passed to readFile
. This is called "hiding" or "shadowing" and happens when a smaller scope declares an identifier that is already declared in a higher scope.
I've written about this here.
If you simply change the name of the nested function's parameters and make sure that within the nested function you refer to those parameter names, it will work:
// The parameters of a function essentially become local variables
// to that function. The names you give will exist throughout that
// function's scope.
function readFile(dirName, ext, callback) {
fs.readdir(dirName, function (err, data) {
if (err) {
return callback(err, null);
}
console.log(ext, data);
// To avoid shadowing/hiding name the nested function's
// arguments something that doesn't conflict with existing
// identifier names in the higher scope.
function filterData(ext2) {
// Now, there is no collission:
console.log(ext2, data);
return data.filter(function(files) {
return arr = files.includes(ext2);
console.log(arr);
});
return callback(null, arr);
}
});
}
Here's a simple example:
var x = 10;
var y = 20;
function foo(){
var x = true; // <-- This x shadows the one from the higher scope
console.log(x,y); // true 20, not 10, 20
}
foo();
console.log(x,y); // 10 20 because the scope of foo is not available here
Upvotes: 1
Reputation: 5422
You are defining param name ext
within the nested function, which shadows the upper scope ext
parameter. So you can change that to something else, and you will have the upper scope ext
param access.
Upvotes: 1