3

I need to store the reference to a constructor of a class in a variable and construct the object later. This is my minimal code example:

function A() {
  var _foo = "A";
}

function Wrapper( constructorFunc  ) {
  var _constructorFunc = constructorFunc;

  this.constructorFunc = function() {
    return _constructorFunc;
  }
}

var wrapper = new Wrapper( A.constructor );
var cFunc = wrapper.constructorFunc();
var obj = new cFunc(); /* obj should be an A now */

I hope it is clear what I would like to do. The Firebug console gives the error TypeError: cFunc is not a constructor. What is the correct way?

Moreover I must be able to "compare" constructors, i.e. I need to know if two references point to the same constructor. (In C++ this would be possible, because one compares the function's address.) As an example:

function A() {
  var _foo = "A";
}

function B() {
  var _bar = "B";
}

function Wrapper( constructorFunc  ) {
  var _constructorFunc = constructorFunc;

  this.constructorFunc = function() {
    return _constructorFunc;
  }
}

var wrapper1 = new Wrapper( A.constructor );
var wrapper2 = new Wrapper( A.constructor );
var wrapper3 = new Wrapper( B.constructor );

wrapper1.constructorFunc() == wrapper2.constructorFunc() /* should evaluate to true */
wrapper1.constructorFunc() == wrapper3.constructorFunc() /* should evaluate to false */

Is this possible?

user2690527
  • 1,729
  • 1
  • 22
  • 38
  • Note: you don't need the `_constructorFunc` variable because the `constructorFunc` function parameter will still be accessible within the same closure. – nnnnnn Nov 02 '14 at 12:37
  • As stated before; constructor is a property of prototype that you get without having to do anything. With inheritance you usually break this property. The following answer may be helpful: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Nov 02 '14 at 15:24
  • @nnnnnn, @HMR: I really love the community here, because one usually gets a good answer within little time. See the answer by dystroy below. It is concise and straight to the point. But I wonder why people start to comment on insignificant flaws of the code, if is cleary stated that the code shall serve as a minimal example. As an example see the discussion below the other answer given by plalx. I believe it should be obvious that in my real code I neither have a class `A`, `B` nor attributes that are called `_foo` or `_bar`. So any discussion if something make "sense" is a waste. – user2690527 Nov 03 '14 at 15:10

2 Answers2

5

The constructor is A, so you must change

var wrapper = new Wrapper( A.constructor );

to

var wrapper = new Wrapper( A );

You can test the result with

console.log(obj instanceof A);

For your second question : there's nothing preventing you to compare constructors (or any function) : two functions are equal when they're the same.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
0

In JavaScript, any function can be a constructor, but function's don't have a constructor property.

Therefore, A.constructor should be changed to just A.

However, functions do have prototypes, and the constructor property of their prototypes refers back to them. Therefore, A.prototype.constructor would work as well, but would be a rather wierd way to refer to A.

If your Wrapper only encapsulates a constructor to return it later it seems that you introduced an unecessary object. Just pass the constructor function around directly.

Finally, you can use the instanceof operator to know if an object is an instance of a specific constructor. The advantage of instanceof over comparing constructor functions together is that the inheritance hierarchy will be considered.

plalx
  • 42,889
  • 6
  • 74
  • 90
  • Of course, my `Wrapper` is much more and it is not even called `Wrapper` in my real code. This is a minimal example. – user2690527 Nov 02 '14 at 14:33
  • @user2690527 Good! Btw, you should define functions such as `constructorFunc` on the prototype. It's much more memory-efficient. Attaching functions directly to the instance is usually considered a bad pratice, unless there's a very good reason to do so. – plalx Nov 02 '14 at 14:37
  • As far as I understand JavaScript this won't work. If I attach `constructorFunc` to the instance, it is a "priviledged" method. This means it is publicly accessible and can access private attributes like `_constructorFunc`. This is what I need and it is called "public method" in other programming language. If I define the function on the prototype, i.e. `Wrapper.prototype.constructorFunc = function() {}` than it is called a "public method" in JavaScript terms but this kind of function is not able to access private attributes. But I need it to return `_constructorFunc`. – user2690527 Nov 03 '14 at 12:42
  • @user2690527 You are totally right about this, however I usually find that priviledged methods aren't worth it. When you go down that path, you will usually end up with most methods having to be priviledged and very little methods on the prototype. There are other alternatives to make a clear distinction between private and public members which doesn't force you to sacrifice the benefits of using prototypes. E.g. http://stackoverflow.com/questions/23819730/make-a-property-that-is-read-only-to-the-outside-world-but-my-methods-can-still/23819811#23819811 – plalx Nov 03 '14 at 12:52
  • Actually, not. Normally I go the following way: (1) Attributes are private. (2) Get- and Set-methods are privileged, so there are at most 2*n such methods, normally much less (3) All other methods are public, i.e. defined on the prototype, because they have access to `this` and can call privileged methods. My "good reasons" for privileged methods are to keep attributes private. I have spent too much time with debugging JS, if one does not follow this path. – user2690527 Nov 03 '14 at 13:12
  • @user2690527 Well, that's one way of doing it, but usually I do not need to expose getters for private variables and don't want to. There are some times where this is useful, but I usually try to follow the Tell don't ask principle where it makes sense. For exemple, if an object had to ask the wrapper for the constructor object it contains to create a new instance, perhaps I would implement an `instanciate` method on the `Wrapper` rather than exposing the wrapped constructor, removing the need for a public getter. – plalx Nov 03 '14 at 13:55
  • @user2690527 In what I described above, public methods would need direct access to *private* variables, without exposing a public getter and in that case I would prefer relying on a naming convention for privates rather than polluting the public interface of my object with getters I don't need. – plalx Nov 03 '14 at 14:00
  • Well, I think this are two totally different philosophies and the discussion starts to flow away from the original question that already has been answered above. As already stated, the `Wrapper` class does not look like this in my (final) code but served as a minimal example to illustrate the actual problem. In my experience relying on naming convention can go dreadfully wrong and it goes twice this way in a language like JS. But we should stop the discussion at this point, because it has nothing to do with the original question. – user2690527 Nov 03 '14 at 14:58