Levi Roberts
Levi Roberts

Reputation: 1317

Is there a better way to return an object and constructor from a constructor function?

I'm trying to return an object along with the constructor function. I have something working but it's kind of ugly and was hoping there was a better way.

function Something(val) {
  if (!(this instanceof Something))
    return new Something(val)

  let Constructor = function() {
    return function(val) {
      return new Something(val)
    }
  }

  let obj = new Constructor()
  obj.test = val
  return obj
}

let a = Something('a')
let b = new Something('b')
let c = b('c')

console.log(a) // { [Function] test: 'a' }
console.log(b) // { [Function] test: 'b' }
console.log(c) // { [Function] test: 'c' }

Thanks for any help.


Edit:

Upon further consideration, I believe more explanation is needed and also decided to approach the problem from a different angle.

Okay, let me see if I can hypothetically articulate my problem. I have a Factory that should resolve to another "class" (although using ES5 function prototypes). This other "class" should be able to have an optional class constructor function along with what we call "class methods". This custom class also needs to be an instance so that it can store data from within it's methods (referring to this)

Ideally, we want the following syntaxes.

const something = Something('customClass') // new keyword is optional
something.someMethod()
// or
something(optionalConfig).someMethod()

In addition to calling the class with the optional constructor, we must also instantiate a new instance.

So that these lines are acting on separate instances:

something.someMethod() // refers to the instance already created
something(optionalConfig).someMethod() // new instance
something(otherOptionalConfig).someMethod() // new instance

Upvotes: 0

Views: 82

Answers (1)

Bergi
Bergi

Reputation: 665584

You seem to be looking for something along the lines of

function Custom(config) {
  function customInstance(moreConfig) {
    return new Custom(config + moreConfig); // not calling Something!
  }
  Object.setPrototypeOf(customInstance, Custom.prototype);
  customInstance.config = config;
  customInstance.test = true
  return customInstance;
}
Custom.prototype = Object.create(Function.prototype);
Custom.prototype.method = function() { … };

const constructors = {Custom, …};
function Something(className) {
  if (!constructors.hasOwnProperty(className)) throw new Error("…");
  return new constructors[className];
}

Given that a Custom constructor and also the Something factory returns a (function) object anyway, the new operator is optional anyway and you don't need to check for it explicitly.

Upvotes: 1

Related Questions