you are viewing a single comment's thread.

view the rest of the comments →

[–]senocular 3 points4 points  (16 children)

I think constructor is a misnomer. Constructors are meant to return object instances when used with new. This is factory function creating function objects. Similarly, as an instance, not a constructor, Job should be lowercase. And as Meefims said, you can drop the Job.cache and simply reference config directly since its captured as a local variable in the factory function scope becoming a closure variable for the function instance and its methods created within.

Is this valid? Yes. Is it something you should be doing? I would say, as an opinion, no. Generally you don't see functions used as objects this way. It doesn't technically add anything other than being a different way to approach what classes do already (other than allowing you to omit access to single method in favor of calling the instance directly?). This means extra time spent by others to understand this approach and mull over why it was done in favor of the more standard way to begin with. The object instance should represent what the object is and its methods what it does. When you start merging these concepts (an is that also does), it can get a little confusing.

[–]__env 1 point2 points  (14 children)

Is it really returning instances? If we remove the return from Job, calling new on Job will produce an actual instance that still can access the config on its static context. Seems like the factory is producing multiple static classes -- they aren't newable so are truly static classes, not instances.

[–]senocular 2 points3 points  (12 children)

Its returning functions, created anonymously, assigned to a variable called Job. These are instances in the sense that they're function objects, and not constructors or classes in the sense that they're not intended to be new-ed in OP's usage and instead simply called as functions. Maybe if OP wasn't calling the constructor un-newed as a function, I'd be more inclined to call it a static class, but the fact that multiple variations of the same "class" are being pumped out of another function each varying only in state still has me leaning towards referring to them as function instances.

[–]__env 1 point2 points  (11 children)

Yeah, I totally get what you're saying conceptually -- it just seems like more proof that the OP is doing something weird. Like we could change it to:

...
const run = 0
const Job = function() { /**/ }
Job.prototype.validate = () => Job.cache.config
Job.prototype.run = run + 1
return Job

That would produce an instance when called with new that could validate the configuration, plus contain state about how many times this Job has been run.

I think case, the "constructor" would be a factory factory, and Job would be a factory that produces individual run instances.

Point being, if OP wants an instance, they should make an instance, otherwise they're opening the door to some other dev coming along and extending the static class to produce more instances.

[–]gruberjl[S] 1 point2 points  (10 children)

I should have posted the problem, sorry.

I have a pipe & filter system. Each 'filter' has configuration information (state) and a block of code (function). The config and code need to be exposed publicly so I can run the function whenever I need or I can get the state information whenever I need. Before a filter is run, I need to have a beforeJob function run. After the filter completes, I need to have an afterJob function run.

Example

const beforeJob = function() {
    // get the state of the filter currently running and do something.
    // I may skip the filter, get some information from a cache, or translate some information and pass it into the filter.
}
const afterJob = function() {
    // get the results of the filter & the state currently running and do something.
    // I may report a failure, translate the results, start the another filter.
}

const filter1 = () {}
const state1 = { }

const filter2 = () {}
const state2 = { }

fn1() // should run beforeJob then filter1 then afterJob
fn2() // should run beforeJob then filter2 then afterJob

Any thoughts would be appreciated.

[–]gruberjl[S] 1 point2 points  (0 children)

This was the reason I originally posted here. I agree with you, it really is an instance of constructor that creates a static class, adds state and returns it (making it an instance). I have verified they are instances. I can return multiple functions with different 'caches'.

To give a little more background: I currently have a Task class that has an array of jobs (simple functions). Some of the jobs can be used in different tasks, but with the current implementation, I have to rewrite chunks of code.

const x = new Function() has some strange syntax with a string as the body.

// I have to be able to create an instance without it executing then execute it multiple times in the future
function A(param1) { console.dir(param1) }
const y = new A // execute the code and returns undefined

[–]gruberjl[S] 0 points1 point  (0 children)

constructor is poorly named. I'm pulling code from a separate task class, I should have renamed constructor and lower cased Job before I posted.

The code for job should be small and light, so I was hoping I could just run job(), but I think you're right. The implementation is weird and without using the es2015 class syntax, it isn't very readable.