Struggling with function prototypes for new node

Hi folks,

I am struggling with some basic Javascript knowledge, to build a new node where I need modules for the first time extensively:

  1. In file myFunctionFile.js, a function is exported:
    module.exports = function myFunction(config) {
       this.existingFunctionality = function() {};
    }
    
  2. After loading that function, new extraFunctionality is added and then the function is stored in a Map:
    var functions = new Map();
    
    var myFunction = require('myFunctionFile.js');
    
    myFunction.prototype.extraFunctionality = function() {};
    
    objects.set('myFunction', myFunction);
    
  3. The function object will be instantiated later in the process:
    var storedFunction = functions.get('myFunction');
    var functionObject = new storedFunction();
    

But functionObject only contains existingFunctionality, but not extraFunctionality.

An extensive search on Google didn't help me. Don't see what I am doing wrong, compared to the code examples that I have found... I don't understand why the new doesn't take into account my prototype changes :woozy_face:

Again any help is appreciated!

Bart

Have you tried calling the extraFunctionality() function?

In a quick test in vscode, the myFunction object doesnt show extraFunctionality ...

image

but it IS in the __proto__ ...

image

and it can be called...

image

1 Like

Thanks again Steve!!!
Yes I couldn't call it. But I provided a simplified example here. Will need to investigate further this evening, and then I will get back here with more info.
Have a nice sunday!

Is it just me? That code seems extremely complex without much in the way of benefits. I think I must be missing something.

Hi Julian,
Yes I am afraid it is just you :joy:

As you can see above it is only a "simplified" code snippet. I extracted only the lines relevant to this issue. Try to imagine a few thousands lines of Javascript code in between...

It was more that you seem to be mixing a number of styles. I guess without understanding what you are trying to achieve, it is hard to understand.

Ok interesting. Can you please explain that a bit more in detail, to make sure I use the correct style for my new node.

Hey @Steve-Mcl,
I still couldn't call the extraFunctionality function this evening in my real node code, but it worked fine in the simplified version like you already pointed out. Seemed after all that my node was calling the code (to add the extraFunctionality function to the prototype) too late in the process.

But thanks to your confirmation that my code should work, I manage to troubleshoot and solve it by simply moving my code snippet to another location...

I really appreciate that you took the time to test my code snippet in VsCode!!!!!!!!
Bart

1 Like

You exported a function in an external module, then added another function to the imported module using a prototype override then you attached that compound object to a map and then instantiate a copy of the compound object later on.

Did I get that right?

Does that not sound somewhat labyrinthine to you?

@TotallyInformation,
Thanks for digging into it!
I will try to explain it, and perhaps you (or someone else) see some points for simplification.

  1. The goal is to allow users to write their own functions into separate files. For example file CustomFunction1.js contains:
    module.exports = function CustomFunction1() {
       this.getName = function() { ... };
       this.getIcon = function() { ... };
       this.getDescription = function() { ... };
       this.calculate = function() { ... };
    }
    
  2. The node reads all the files and builds a catalog of functions:
    var functionCatalog = new Map();
    
    for (var i = 0; i < functionFileNames.length; i++) {
       var customFunction = require(functionFileNames[i]);
       functionCatalog.set(functionFileNames[i], customFunction);
    }
    
  3. Later on the node uses the functionCatalog in all kind of places (in the config screen, in the calculations, ...).

Moreover all the CustomFunctions need to contain a shared function. Since I want to keep the files as simple as possible, so I wanted to add the shared functions in step 2:

var customFunction = require(functionFileNames[i]);
customFunction.prototype.sharedFunction = function() { ... };
functionCatalog.set(functionFileNames[i], customFunction);

Hopefully it is a bit more clear now to understand what I want to achieve ...

Thanks, that is much clearer now.

I don't think that needs to be a function. It can just be an object I think which should save some confusion.

module.exports = {
    getName: function() { ... },
    ...
}

You would have to test whether the prototype addition works though. I think it would but I'm not as much of an expert as my ego would make out! Actually, thinking about it, if the input module is an object, you can simply add the shared function to the object, you don't need to mess with the prototype at all.

I'm not totally clear if you are trying to handle files from multiple users or multiple files from 1 user. If the latter, if you could stipulate that the function names have to be unique across those user files, I think you could also get rid of the map? You would just be able to merge the objects. You could even make the merge more intelligent by either throwing a warning on a duplicate name or just adding a number to it until it goes in.

Of course, I've probably completely mangled your idea!

Yes that is easier to understand.
I had started from the example of a Node-RED node:

module.exports = function(RED) {
    ...
}

But indeed for my use case a simple object is better...

Even better ...

Me neither. It is currently only a POC, so I will keep the map at the moment. Let's see how it evolves....

Absolutely :joy:
But in this early stage I don't mind at all. I prefer to have the basics correctly ...

The only thing I'm wondering now: I can have N instances of a single CustomFunction1 in my node. Previously this was easy, because by calling the CustomFunction1 it was filled with instance data. But now I have to start cloning that object from my catalog. Need to think about that.

But now off to work...

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.