leo277
leo277

Reputation: 445

JAVASCRIPT CLASS instance default method

I recently went for an interview and got a question on JAVASCRIPT which I could not answer, but i would really like to know the answer, but I do not know how to phrase it in google.

The question is:

var a = new A();
a(); // return 1
a(); // return 2

var b = new A();
b(); //return 1;
b(); //return 2;

Implement A

How can I solve this using javascript. I got this so far

class A {
  constructor(){
    this.num = 1;
  }
  function(){
    console.log(this.num--);
  }
}

Upvotes: 1

Views: 1756

Answers (4)

Estus Flask
Estus Flask

Reputation: 222498

This is XY problem. There is no requirement to use ES6 class in interview question. It is misused here because it cannot provide any reasonable class design (it makes no sense from OOP point of view and requires unreasonable prototype hacking from JS point of view).

There is no such thing as 'default' method, this isn't how OOP works. new creates an instance of a class, and in order to receive a function as an instance, a class should be a child of Function, so this answer is technically correct, although impractical.

The answers don't really explain that, but the proper answer to this interview question is:

New function should be returned from constructor function.

function A(num = 0) {
  return () => ++num;
}

var a = new A();
a(); // return 1
a(); // return 2

It is workable, but there is no reason to use this function as a constructor. It's expected that class instance is used to store and expose num state, and there is no good way to use this as class instance in this capacity because prototypal inheritance between constructor and returned function weren't established. new provides additional overhead without any purpose. The solution is purely functional, and the use of new is the mistake, so it should be omitted.

var a = A();
a(); // return 1
a(); // return 2

And there is a good chance that the one who asks the question will be frustrated by the answer; it's unlikely that this was a catch for A+ answer.

Upvotes: 3

Ori Drori
Ori Drori

Reputation: 191986

When using the new operator, A class constructor or a function can return a value other than this. According to MDN:

The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

So a possible answer to this question is to return a function from the constructor:

class A {
  constructor(){
    this.num = 1;
    
    return this.func.bind(this); // bind the function to `this`
  }
  
  func() {
    console.log(this.num++);
  }
}

var a = new A();
a(); // return 1
a(); // return 2

var b = new A();
b(); //return 1;
b(); //return 2;

Possible uses:

After answering this question, I've started to think about the legitimate uses of the return value.

  1. Singleton

class Singleton {
  constructor() {
    if(Singleton.instance) {
      return Singleton.instance;
    }
    
    Singleton.instance = this;
    
    return this;
  }
}

console.log(new Singleton() === new Singleton()); // true

  1. Encapsulated module using the Revealing Module Pattern with a class

class Module {
  constructor(value) {
    this.value = value;
    
    return {
      increment: this.increment.bind(this),
      decrement: this.decrement.bind(this),
      getValue: this.getValue.bind(this),
    };
  }
  
  increment() {
    this.value++;
  }
  
  decrement() {
    this.value--;
  }
  
  getValue() {
    return this.value;
  }
}

const module = new Module(5);

module.increment();
module.increment();
module.decrement();

console.log(module.value); // undefined
console.log(module.getValue()); // 6

Upvotes: 4

mika
mika

Reputation: 1451

class A {
  constructor () {
    this.num = 1
    return () => {
      console.log(this.num++)
    }
  }
}

Upvotes: -1

deceze
deceze

Reputation: 522165

It is unclear whether using a class is required; here's a solution using a simple closure and basically ignoring the new keyword:

function A() {
    var i = 1;
    
    return function () {
        console.log(i++);
    }
}

var a = new A();
a();
a();

var b = new A();
b();
b();

Upvotes: 4

Related Questions