AngularJS controllers and "use strict"

Chris Bier picture Chris Bier · Oct 18, 2012 · Viewed 61.7k times · Source

I recently started using JSHint and it is requiring me to use the function form of "use strict". Since then, AngularJS throws an error:

"Error: Argument 'webAddressController' is not a function, got undefined"

When I remove the function form of "use strict" the controller loads fine.

Controller:

(function () {
    "use strict";

    function webAddressController($scope, $rootScope, web_address_service) {
             // Do things
    }

}());

Does anyone have any insight on what's going on here?

Answer

Ben Lesh picture Ben Lesh · Oct 19, 2012

First off, I want to state the pkozlowski really knows his stuff at Angular, but this actually isn't as much of an Angular issue as it is an issue with closure.

Angular is looking for controllers in two places:

  1. in its own registry of controllers registered via Module.controller()
  2. In a global variable (or global function declaration)

The problem is that everything inside your closure for "use strict" is not global. It's wrapped up and privatized in the anonymous function containing it.

(function() {
   // nothing in here is global or even public.
   // "use strict" or not.

   "use strict"; // this is mostly irrelevant.

   // this will not work, because it's wrapped and not global
   function ThisDoesntWork($scope) {
   };

   // window is the global root variable. So this works.
   window.ThisWorks = function($scope) {

   };

   // this will work, because it's explicitly registering the controller
   // presuming app is your Module variable from outside of the closure.
   app.controller('ThisIsBest', function($scope) {

   });

})();

//this works because it's global.
function ThisAlsoWorks($scope) {

}

// if you declare a global var, then set it inside
// of your closure, you're good to go too.
var ThisWillWorkToo;

(function {
    //here we're setting it again.
    ThisWillWorkToo = function($scope) {
    };
})();


// if you're really crazy you can even do this...
 var ThisWillWorkButItsWeird = (function() {
      "use strict";

       function ThisWillWorkButItsWeird($scope) {

       }

       return ThisWillWorkButItsWeird;
  })();

At the end of the day, you can put "use strict" inside any function, or at the file level if you like. "use strict" itself isn't breaking anything for you. There are a thousand ways to register a controller, as you can see. The best choice is probably to just explicitly register them with the .controller method as suggested.