28

我最近开始使用 JSHint,它要求我使用“use strict”的函数形式。从那时起,AngularJS 抛出一个错误:

“错误:参数 'webAddressController' 不是函数,未定义”

当我删除“使用严格”的功能形式时,控制器加载正常。

控制器:

(function () {
    "use strict";

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

}());

有人对这里发生的事情有任何见解吗?

4

4 回答 4

44

首先,我想说 pkozlowski 真的很了解他在 Angular 的工作,但这实际上并不是一个 Angular 问题,而是一个闭包问题。

Angular 在两个地方寻找控制器:

  1. 在自己的通过 Module.controller() 注册的控制器注册表中
  2. 全局变量(或全局函数声明)中

问题是“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'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;
  })();

归根结底,您可以将“use strict”放在任何函数中,或者如果您愿意,也可以放在文件级别。“使用严格”本身并没有为您破坏任何东西。如您所见,有上千种注册控制器的方法。最好的选择可能是按照建议使用 .controller 方法显式注册它们。

于 2012-10-19T03:28:28.197 回答
14

我想 JSHint 在这里试图告诉你的是避免使用全局变量(这显然是一个非常好的做法!)。

AngularJS 对解决相同问题(即避免使用全局变量)的看法略有不同,并允许您在模块中定义控制器(使用全局angular命名空间)。您可以使用如下模块重写您的示例:

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

这是在实践中说明这一点的 jsFiddle:http: //jsfiddle.net/t3vBE/1/

使用这种方法,您不会使用控制器构造函数污染全局命名空间。

angular如果要使用严格模式,则需要更改 JSHint 配置以允许全局变量。或者,您也可以将整个代码(再次使用模块)包装到一个立即执行的函数中:

(function () {
    "use strict";

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

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

}());​

这是 jsFiddle:http: //jsfiddle.net/t3vBE/4/

对我来说,这只有在你想定义纯 JavaScript、“帮助”函数时才有意义,否则我会依赖 AngularJS 服务。

于 2012-10-18T17:42:00.280 回答
4

如果您的角度模块已经在其他地方加载,另一种方法是 @pkzolowski 正在做的事情:

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

它基于此处的评论: angularjs为不同文件中的同一模块定义服务

请注意,使用 angular.module('myModule', []) 将创建模块 myModule 并覆盖任何名为 myModule 的现有模块。使用 angular.module('myModule') 检索现有模块。

于 2014-08-01T21:30:32.707 回答
2

你有没有试过在 (function()

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

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

}());

我的回答是基于我看到的Yeoman生成的文件

于 2017-05-12T15:23:41.287 回答