I'm trying to process some json and write pieces of data to a few files.
So I have a function to create folder/files based on the json data and some literals. The filenames are defined by an object containing different categories:
const folders = {
category1: {
fileName: 'default',
path : '/path',
subpath : () => `/subpath/${this.fileName}${this.uniqueId}`
}
}
This is where half of you will jump ahead and tell me that arrow functions can't see this
of their own objects etc. I know that and that's intentional, since I'll be getting the necessary data later on.
The main function follows this pattern:
function readSave() {
//suppose readFileSync would return a string 'filename' and an int 1029
this.fileName = 'filename';
this.uniqueId = 1029;
let filePath = folders.category1.path + folders.category1.subpath();
// I'd go on to write stuff to that file but for now let's just return
return filePath;
}
readSave()
// returns '/path/subpath/undefinedundefined'
// expected '/path/subpath/filename1029'
I also know that I could just pass fileName
and uniqueId
as args but that's not the point. This post is not exactly an attempt to find a solution but to understand why it's not working.
The confusion here is the use of this
inside readSave
. According to MDN this
inside a regular function is the same object where the function is called. Since I'm calling it on a plain js file on node, it's global
.
All good for now. If I inspect the run inside the function call, this
is global
and the properties are set without problems.
The problem is folders.category1.subpath()
evaluates to undefined
.
The debugger shows when it goes to evaluate () => /subpath/${this.fileName}${this.uniqueId}
, this
is not global
anymore, instead it's an empty Object. This doc makes me think that the arrow function should inherit the this
of the scope it's being called, which is readSave
, which means this
should be global
.
To increase my confusion, setting the properties outside the function works flawlessly:
function readSave2() {
let filePath = folders.category1.path + folders.category1.subpath();
return filePath;
}
this.fileName = 'filename';
this.uniqueId = 1029;
readSave()
// returns '/path/subpath/filename1029'
Inspecting the code above, everything is pretty much the same up until when it goes to evaluate () => /subpath/${this.fileName}${this.uniqueId}
. Now the previously empty Object has two properties as they were set.
Finally, this also works exactly the same as the previous example:
const readSave3 = () => {
this.fileName = 'filename';
this.uniqueId = 1029;
let filePath = folders.category1.path + folders.category1.subpath();
return filePath;
}
I've browsed and read about this for hours but am still really confused as to why some methods work and some don't.
Thanks in advance
Update: Turns out I made some wrong assumptions on what Node's root object is in a given file or function call. Wasn't really aware of the module wrapper.