0

Is it possible to get same instance when using new keyword in javascript. I know it is not a good idea just wondering if it is possible to do something with Test function so it return same object.

Ex

var a = new Test();
var b = new Test();
a == b // should give true
Arin
  • 632
  • 6
  • 16

3 Answers3

2

Is it possible to get same instance when using new keyword in javascript?

Yes:

var a,
    b;

function Test() {
  if (Test._instance) {
    return Test._instance;
  }
  Test._instance = this;
}

a = new Test();
b = new Test();

console.log(a === b);

I know it is not a good idea…

I've written about this as an implementation of the Singleton (anti)pattern in JavaScript. You're right in that it's not a good idea. In fact, I'd recommend never using this pattern in any production environment. There are much better patterns available in JS, and a constructor that always returns the same data might as well be a plain function.

var getTest,
    a,
    b;

getTest = (function () {
  var test;
  function Test() {
  }

  function getTest() {
    if (!test) {
      test = new Test();
    }
    return test;
  }
  
  return getTest;
}());

a = getTest();
b = getTest();

console.log(a === b);
Community
  • 1
  • 1
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • 1
    Worth noting that Singletons (this pattern) is wildly considered as a bad practice because it promotes bad design that's relying on global variables. Beware when using it! – Madara's Ghost Jun 29 '16 at 13:53
  • @MadaraUchiha, it was already mentioned in the question. I will soon be adding it to my answer though, as "yes" is a pretty terse answer. – zzzzBov Jun 29 '16 at 13:54
0

The problem with your code is that it's unintuitive. I expect new to return a new instance every time. If you still want to do it with your exact code, use zzzzBov's answer.

I propose an alternative API:

function Test() {
  // my constructor
}

Test.getInstance = () =>  {
  if (!Test._instance) { Test._instance = new Test(); }
  return Test._instance;
}

And call with

const a = Test.getInstance();
const b = Test.getInstance();

console.log(a === b); // true

This doesn't protect you against direct calls to new Test() though, so it can be bypassed. To truly enforce a single instance, hide Test behind a closure:

const getTestInstance = (() => {
  function Test() {
    // my constructor
  }

  let instance;

  const getInstance = () =>  {
    if (!instance) { instance = new Test(); }
    return instance;
  }

  return getInstance;
})();

Now only getTestInstance is exposed, you can't use new Test() anymore.

Note: Just writing this code made me puke a little inside my mouth. Please don't use it unless you've evaluated all of your options and know of the price associated with introducing Singletons into your design.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
-2

It is possible. If you return any value from a function, and the new operator will return that object instead of a new one.

var testInstance = {name:"test"};
function Test() {
  return testInstance;
}

var a = new Test();
var b = new Test();

console.log(a === b);
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
  • That's cheating. Your constructor isn't really a constructor and you can't add logic to it like any other constructor. – Madara's Ghost Jun 29 '16 at 13:55
  • @MadaraUchiha A constructor is just a plain function in javascript. There is no point telling "its not a real constructor". Furthermore the question didn't even have the word "constructor". And why would you add a logic to a function that returns the same object every time anyway? A valid reason is if you want a lazy initialized singleton. But in that case you shouldn't even expose a constructor. If you want logic that runs once you can place after the declaration of the function, and setup `testInstance` as you want. But of course you already know all of this, I just wanted to defend my point – Tamas Hegedus Jun 29 '16 at 14:06
  • Maybe I should remove the word constructor from my answer – Tamas Hegedus Jun 29 '16 at 14:07
  • Of course there's a such a thing as "constructor", it's a function you call with the `new` operator. And the contract you supply to your consumers is that when you call `new` you get a new object, often with some sort of initial state you pass in the parameters. You didn't initialize the object on the first call to `Test` you initialized it before hand. – Madara's Ghost Jun 29 '16 at 14:14
  • @MadaraUchiha Thats right, I do not initialize the object on the first call, as nobody asked for it. I removed the use of the word "constructor" so nobody else gets confused by the definitions. – Tamas Hegedus Jun 29 '16 at 14:33