Контроллеры AngularJS и "использовать строгое"

Я недавно начал использовать JSHint, и он требует, чтобы я использовал функциональную форму "use strict". С тех пор AngularJS выдает ошибку:

"Ошибка: аргумент" webAddressController "не является функцией, получил неопределенное значение"

Когда я удаляю функцию вида "использовать строгий", контроллер загружается нормально.

контроллер:

(function () {
    "use strict";

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

}());

У кого-нибудь есть понимание того, что здесь происходит?

4 ответа

Решение

Прежде всего, я хочу заявить, что Пкозловский действительно знает свое дело в Angular, но на самом деле это не столько проблема Angular, сколько проблема с закрытием.

Angular ищет контроллеры в двух местах:

  1. в своем собственном реестре контроллеров, зарегистрированных через Module.controller()
  2. В глобальной переменной (или объявлении глобальной функции)

Проблема в том, что все, что в вашем закрытии для "строгого использования", не является глобальным. Он упакован и приватизирован в анонимной функции, содержащей его.

(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;
  })();

В конце дня вы можете использовать "строгий режим" внутри любой функции или на уровне файлов, если хотите. "используйте строгий" сам по себе ничего не нарушает. Как видите, существует тысяча способов зарегистрировать контроллер. Наилучшим выбором, вероятно, будет просто явно зарегистрировать их с помощью метода.controller, как это предлагается.

Я думаю, что JSHint пытается сказать вам здесь, чтобы избежать глобальных переменных (что, очевидно, очень хорошая практика!).

AngularJS имеет немного другое мнение о решении той же проблемы (то есть - обойти глобальные переменные) и позволяет вам определять контроллеры в модулях (используя глобальные angular Пространство имен). Вы можете переписать свой пример, используя такие модули:

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

Вот jsFiddle, иллюстрирующий это на практике: http://jsfiddle.net/t3vBE/1/

При таком подходе вы не загрязняете глобальное пространство имен конструкторами контроллеров.

Вам нужно будет изменить конфигурацию JSHint, чтобы angular глобальная переменная, если вы хотите использовать строгий режим. В качестве альтернативы вы также можете заключить весь код (снова используя модули) в функцию, которая выполняется сразу же:

(function () {
    "use strict";

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

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

}());​

Вот jsFiddle: http://jsfiddle.net/t3vBE/4/

Для меня это имеет смысл, только если вы хотите определить чистый JavaScript, "вспомогательные" функции, в противном случае я бы положился на сервисы AngularJS.

Еще один способ сделать то, что делает @pkzolowski, если ваш угловой модуль уже загружен в другом месте:

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

Это основано на комментарии отсюда: angularjs, определяющий сервисы для одного и того же модуля в разных файлах

Помните, что использование angular.module('myModule', []) создаст модуль myModule и перезапишет любой существующий модуль с именем myModule. Используйте angular.module('myModule'), чтобы получить существующий модуль.

Вы пытались написать "используйте строгий" снаружи и до (функция ()

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

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

}());

Мой ответ основан на файлах, которые я видел, сгенерированные Yeoman

Другие вопросы по тегам