1

I spent some time on something I thought was a bug until I found a workaround.

Still I can't understand why the previous code failed.

Any insight please?

Failing code:

getModule: ->
  Gmaps4Rails.Google

createMap : ->
  new @getModule().Map()

Working code:

constructor:
  @module = @getModule()

getModule: ->
  Gmaps4Rails.Google

createMap : ->
  new @module.Map()
apneadiving
  • 114,565
  • 26
  • 219
  • 213

1 Answers1

3

The reason is that new anonymous function is not the same as new Gmaps4Rails.Google() in JavaScript.

// Translated JavaScript code (simplified):

var your_module = {
    getModule: function() {
        return Gmaps4Rails.Google;
    },
    createMap: function() {
        // This is where things go wrong
        return new this.getModule().Map();
    }
};

The problem is that return new this.getModule().Map(); translates to return new function() { return Gmaps4Rails.Google; } - which ignores the return value and uses this (which is a new object inheriting from the anonymous function). Thus the line essentially translates to return {}.Map(); Since objects do not have a Map method, you get an error.

When you set @module to be a reference to Gmaps4Rails.Google then when you call new @module.Map() you are actually calling new Gmaps4Rails.Google - and it returns an object which has a Map method - thus everything works.

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • I'd have understood if I'd written: `new this.getModule.Map()` but it's not the case. This translates to: `return new function() { return Gmaps4Rails.Google; }()` I guess – apneadiving Aug 14 '12 at 19:39
  • @apneadiving - essentially - it would be closer to translate it as `var _temp = function() { return Gmaps4Rails.Google; }; return new _temp();` – Sean Vieira Aug 14 '12 at 19:41
  • So `this` inherits from `Gmaps4Rails.Google` then `this.Map()` is triggered? Sounds crazy to me :) (+1 in the meantime) – apneadiving Aug 14 '12 at 19:48
  • @apneadiving - no, not at all - in the broken version the returned value from the anonymous function (`this`) is an object that inherits from the anonymous function. In the working version `@module` is a *reference* to the actual function you want to call `new` on (`Gmaps4Rails.Google`) rather than a different (anonymous) function altogether. Does that make sense? – Sean Vieira Aug 14 '12 at 19:54
  • I guess it's te best answer I can get so I accept it, but do you know where I could find the theory around this please? – apneadiving Aug 14 '12 at 19:57
  • @apneadiving - [bobinc's answer](http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript/1598077#1598077) is quite good as is [killdream's article](http://killdream.github.com/blog/2011/10/understanding-javascript-oop/index.html#sec-4-1) and the [MDN reference](https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript) – Sean Vieira Aug 14 '12 at 20:11