21

I'm writing a quite complex JavaScript application that has an MVC architecture that I'm implementing using Prototype's Class support and the Module pattern. The application uses AJAX and the Observer pattern. I create my controller instance when the DOM has loaded, pass it a view and some models created from JSON data and away it goes.

However, I've found that I have to set my controller instance as a property on the Window object—i.e. declare it without using var—because I have an AJAX success callback that refreshes the view object owned by the controller and at this point in the code my nice little MVC world is not in scope.

I investigated passing in the view object as a parameter to the function containing the AJAX code, but this got really messy and would have led to some horrible violations of the MVC pattern, such as coupling the model and the view. It was horrendous.

Is doing things like storing my controller instance directly on Window considered bad form? It smells a bit like using a global variable to me, but I can't see any way around it.

John Topley
  • 113,588
  • 46
  • 195
  • 237
  • Can you post a small code sample? – Ryan Doherty Sep 09 '10 at 18:57
  • I can't I'm afraid. I'm at home and the code is at work and more importantly, I think I would have to post a significant amount of code to illustrate the point - I don't like reading "wall of text" questions so I wouldn't want to inflict it on others! – John Topley Sep 09 '10 at 19:00
  • 1
    Why would the MVC be out of scope? Should not at least a reference to it be captured in a closure by your AJAX callback? – MooGoo Sep 09 '10 at 19:04
  • I'm not too proficient with closures. Essentially the AJAX function is within the controller and it gets invoked by a model function that itself gets invoked by an update to another model instance (hence the Observer pattern). I'm using Prototype's `onSuccess` callback and `this` at that point refers to `Window`. – John Topley Sep 09 '10 at 19:15
  • 1
    Then simply put something like `var that = this` right before the callback code, then change all references to `this` in the callback to `that`. Alternatively, use Prototype's [`Function.bind`](http://www.prototypejs.org/api/function/bind) to fix the value of `this` – MooGoo Sep 09 '10 at 19:33

3 Answers3

14

Setting properties on the window object is equivalent to creating global variables. That is, sometimes doing it is inevitable, but you should try to keep it to a bare minimum, as it ends up polluting the global namespace.

In your case, creating a single property is not so bad. If you want to be extra careful about it, you can explicitly create a namespace for any stuff you need global access to:

// In init:
var mynamespace = {};

. . .

// Once the controller is available:
var namespace = window.mynamespace;
namespace.controller = controller;
namespace.foo = bar; // Set other stuff here as well.
levik
  • 114,835
  • 27
  • 73
  • 90
3

I would say it's bad practice. You can always, and easily, create a namespace for your application and put globals in there, if you must.

John Topley
  • 113,588
  • 46
  • 195
  • 237
hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
2

They are useful when you want to call a global function whose name is not known beforehand.

var funcName = "updateAns" + ansNum;
window[funcName]();

They can be used to a) avoid evil evals in most cases. b) avoid reference errors to global variables.

x = x + 1 will generate a reference error if a global x is not defined. window.x = window.x + 1 will not

letronje
  • 9,002
  • 9
  • 45
  • 53