1

Consider the simple code below:

function C1() {
  let x=5;
}

var c1=new C1;
alert(c1 instanceof C1); // returns true


function C2() {
  let x=5;
  
  return { 
    getx() { return x; } 
  }
}

var c2=new C2;
alert(c2 instanceof C2); // returns false ! why ??

Questions:

  1. why is c2 not an instance of C2 ?

  2. how can I have a constructor returning an object (ie C2) and still have new returning an instance of that constructor WITHOUT changing C2 ?

kofifus
  • 17,260
  • 17
  • 99
  • 173
  • Because it returns an object that does not inherit from `C2.prototype`? Why would you want to return an object?! – Bergi Sep 01 '16 at 04:49
  • I need it for this https://github.com/kofifus/BetterES6Classes ... works really well :) – kofifus Sep 01 '16 at 05:59
  • No, I can't imagine that works well. You've got absolutely no story for subclassing and `this` inside your classes doesn't refer to what you might think it does. Also the constructor syntax is really ugly, fails at creating public properties, and creates even more unnecessary functions than you need for private variables. – Bergi Sep 01 '16 at 06:12
  • Btw, that reason "*Error prone - especially the issue of 'this' inside private methods not referring to the instance unless you remember the confusing 'that=this' hack*" is invalid when you're using arrow functions, and can't be mitigated at all when you're not. – Bergi Sep 01 '16 at 06:13
  • fixed the 'this' issue, have a look ... yes no support for subclassing as documented, working on supporting composition – kofifus Sep 03 '16 at 04:04
  • added composition – kofifus Sep 03 '16 at 06:22

3 Answers3

3

why is c2 not an instance of C2 ?

Because C2.prototype is not in the prototype chain of c2. c2's only object in the prototype chain is Object.prototype.

how can I have a constructor returning an object (ie C2) and still have new returning an instance of that constructor ?

You need to put the prototype object of the constructor in the prototype chain of the object.

E.g.

function C2() {
  let x=5;

  return Object.create(C2.prototype, {
    getx: {value: function() { return x; }},
  });
}

That's what you get for free with this inside the constructor, so you could as well just do:

function C2() {
  let x=5;
  this.getx = function() { return x; };
}

WITHOUT changing C2

You can change the prototype of an existing object via Object.setPrototypeOf (this method is can deoptimize code).

function C2() {
  let x=5;

  return { 
    getx() { return x; } 
  }
}

var c2=new C2;
Object.setPrototypeOf(c2, C2.prototype);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • thx! I want to achieve this WITHOUT changing the definition of C2. I changed my question accordingly. – kofifus Sep 01 '16 at 04:46
  • You could do `Object.setPrototypeOf(c2, C2.prototype)` after the instance was created. But I'm not sure how widely supported that method is. (looks like browser support is OKish: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf ) . Other than that, there is no way. – Felix Kling Sep 01 '16 at 04:48
  • great, Object.setPrototypeOf(c2, C2.prototype) works well ! if you can post updated code I'll mark it as answered – kofifus Sep 01 '16 at 04:54
  • 1
    @kofifus: You [really shouldn't use that](http://stackoverflow.com/q/23807805/1048572). – Bergi Sep 01 '16 at 06:14
1

This should work:

 function C2() {
    let x=5;
    this.getx = function() {
        return x;
    };
 };

Understand that when you call new you create a new object, and this object will be referencable via the this keyword within the function.


If you have a function returning a value, you end up simply getting that value. This should demonstrate:
function C2() {
   let x=5;

   this.getx = function() {
     return x;
   };
   return new C1;
}

var c2=new C2;
alert(c2 instanceof C1); // returns true
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
-1

With you need create a new object use Class, you can´t create a new function of function. Or you need to use prototype

class C1 {

 constructor(){
  this.x=5;
 }
}

var c1=new C1();
alert(c1 instanceof C1); // returns true


class C2 {
  constructor(){
  this.x=5;
 }
  
 getx(){
 return x; 
}

}

var c2=new C2;
alert(c2 instanceof C2); // returns false ! why ??