By Chris Bier


2012-10-18 14:56:49 8 Comments

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?

4 comments

@Siddhesh T 2017-05-12 15:23:41

Have you tried writing 'use strict' outside and before (function()

"use strict"; // <-- add it here
(function () {
    //"use strict"; <-- remove from here

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

}());

My answer is based on the files that I have seen generated by Yeoman

@zeusstl 2014-08-01 21:30:32

Another way to do what @pkzolowski is doing if your angular module is already loaded elsewhere:

var app = angular.module('myApp');
app.controller(...);
app.service(...);
...

It is based on the comment from here: angularjs defining services for the same module in different files

Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.

@Ben Lesh 2012-10-19 03:28:28

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.

@pkozlowski.opensource 2012-10-18 17:42:00

I guess that JSHint is trying to tell you here is to avoid global variables (which is obviously a very good practice!).

AngularJS has slightly different opinion about solving the same problem (that is - avoiding global variables) and allows you to define controllers in modules (using a global angular namespace). You could rewrite your example using modules like this:

angular.module('myApp',[]).controller('webAddressController', function($scope) {
    // Do things
});

Here is the jsFiddle illustrating this in practice: http://jsfiddle.net/t3vBE/1/

With this approach you are not polluting global namespace with controller constructors.

You will need to change the JSHint configuration to allow angular global variable if you want to use the strict mode. Alternatively you could also wrap your whole code (once again, using modules) into a function that gets executed imediatelly:

(function () {
    "use strict";

angular.module('myApp',[]).controller('webAddressController', function($scope) {

    $scope.name = 'World';
    // Do things
});

}());‚Äč

Here is the jsFiddle: http://jsfiddle.net/t3vBE/4/

For me this makes sense only if you want to define pure JavaScript, "helper" functions, otherwise I would rely on AngularJS services.

@Florian F 2013-04-16 08:00:03

any idea how I could automate the task of wrapping all my angular code in a IIFE with a 'use strict' declaration ? (I'm using grunt)

@Michael J. Calkins 2014-01-13 21:43:23

@FlorianF I personally use LiveTemplates in WebStorm

@Carl G 2014-04-16 02:59:01

The jshint warning is not exactly to prevent global variables, but to prevent a similar problem of a global "use strict". If you concatenate files together (a common build step) the top-level "use strict" will apply to all following files (even if they were not written to conform to jshint.) The function form limits jshint to that function only.

Related Questions

Sponsored Content

24 Answered Questions

[SOLVED] Combating AngularJS executing controller twice

  • 2013-03-20 21:43:16
  • Greg
  • 169107 View
  • 532 Score
  • 24 Answer
  • Tags:   angularjs

28 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

6 Answered Questions

[SOLVED] How do I use $scope.$watch and $scope.$apply in AngularJS?

18 Answered Questions

[SOLVED] Insert HTML into view from AngularJS controller

7 Answered Questions

[SOLVED] 'this' vs $scope in AngularJS controllers

28 Answered Questions

19 Answered Questions

[SOLVED] How do I access the $scope variable in browser's console using AngularJS?

14 Answered Questions

[SOLVED] How does data binding work in AngularJS?

30 Answered Questions

Sponsored Content