8

A very puzzling problem i am having with JavaScript. look at the code below..

az={
   classes:{
      test:function(){
        this.hello=function(name){
          alert('hello '+name);
        }
      }
   },
   getClass:function(name){
    return az.classes[name];
   }
};
var a=new az.classes['test']();
a.hello('foo');
var b= new az.getClass('test')();
b.hello();// fails !!!

in the code if you notice we have a class defined inside an object az.classes. when try to create an instance of that class by new az.classes['test](), it works and a.hello() executes fine. but when i call the method az.getClass('test'), which in turn returns the same constructor, but it fails when i say var b=new az.getClass('test'); here its saying b is undefined!! and b.hello() fails!! i do not understand this behaviour! what is the difference between new az.classes['test']() and new az.getClass('test'). Are they not the same thing??

2
  • 1
    try var b= new (az.getClass('test'))(); instead. then b will be like a Commented Apr 24, 2013 at 5:34
  • @gurvinder372 You must be reading a different question to me. I see getClass:function(name) Commented Apr 24, 2013 at 5:35

4 Answers 4

5

When instantiating a constructor, the first parens indicate what to use at the constructor.

So new az.classes['test'](); will execute the expression az.classes['test'] and use the resulting function as the constructor.

Or refactored, it does this:

// new az.classes['test']()
//                       ^ expression left of here used as constructor!
var MyConstructor = az.classes['test'];
new MyConstructor();

However, new az.getClass('test')(); executes the expression az.getClass which returns your class getter function, and attempts to use that as the constructor. Then your instance tried to be executed with the ().

Or refactored, it does this:

// new az.getClass('test')();
//                ^ expression left of here used as constructor!
var MyConstructor = az.getClass;
var instance = new MyConstructor('test');
instance(); // obviously not gonna work.

See the difference?

You can solve this by wrapping more parens around the expression that should return the constructor:

new (az.getClass('test'))();
//                       ^ expression left of here used as constructor!

Or by saving the constructor reference to a local variable, and then using it on the next line. This is probably more sane and readable:

var MyConstructor = az.getClass('test');
new MyConstructor();
//               ^ expression left of here used as constructor!
Sign up to request clarification or add additional context in comments.

Comments

3

A constructor function in JavaScript can return a value, which replaces the value which would normally be returned by the "new" expression.

So new az.getClass("test")() will first evaluate az.getClass("test") which will return a function. You are then invoking that function with () which will return undefined since it has no return value.

1 Comment

+1, the other answer was in fact slightly wrong - operator precedence dictates that new is called after ().
1

It's a problem with parenthesis (operator precedence). This should work:

var b = new (az.getClass('test'))();

http://jsbin.com/odajet/1/edit

Comments

0

var b = new az.getClass('test')();

is equivalent to first getting the class:

var b = new az.classes.getClass('test');

b is now the class az.test, not an instance of it.

and then:

b = b();

calling the class constructor with the global object as this

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.