Угловые контроллеры и "использовать строгие" - программирование

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

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

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

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

Контроллер:

(function () {
    "use strict";

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

}());

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

4b9b3361

Ответ 1

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

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

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

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

(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 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 explicitly registering the controller
   // presuming app is your Module variable from outside of the closure.
   app.controller('ThisIsBest', function($scope) {

   });

})();

//this works because it 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, как это было предложено.

Ответ 2

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

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

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

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

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

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

(function () {
    "use strict";

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

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

}());​

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

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

Ответ 3

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

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

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

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

Ответ 4

Вы пытались написать 'use strict' снаружи и раньше (function()

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

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

}());

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