我过去已经回答过这个问题,但你问这些问题很好。
$rootScope 存在,但它可以用于 Angular 形式的层次结构中的邪恶作用域,原型是从树顶部的根作用域继承的。通常这可以忽略,因为大多数视图都有自己的控制器,因此也有自己的作用域。
非隔离作用域是分层的,但大多数开发人员应该使用具有隔离作用域的指令。AngularJS 范围的层次结构是 Angular应用程序中许多错误的根源。这是一个我喜欢称之为范围出血的问题,其中范围属性在 DOM 树中的某处被神奇地修改,而你不知道为什么。
Angular 的默认行为是针对固有范围,这使得一个控制器很容易更新由另一个控制器管理的内容,依此类推。这就是创建源代码之间的意大利面条式连接的方式。使维护该代码变得非常困难。
有时,您希望将一些数据全局化到整个应用程序。对于这些,您可以像任何其他范围一样注入 $rootScope 并在其上设置值。
不,那是不正确的。AngularJS 允许您定义诸如常量、值和服务之类的东西。这些是可以注入到路由、控制器和指令中的东西。这就是你如何让你的应用程序全局访问事物,如果你想让你的控制器或指令可测试,你将如何做到这一点。单元测试编写者不知道指令或控制器所依赖的 $rootScope 中应该有哪些属性。他们必须假设 $rootScope 没有发生变异以提供服务或数据。
当然,全局状态很糟糕,您应该谨慎使用 $rootScope,就像您(希望)在任何语言中与全局变量一起使用一样。
问题不在于 $rootScope,而在于人们用它做什么。许多应用程序将当前用户、身份验证令牌和会话数据添加到 rootScope 中。这最终在模板中被大量使用(如果用户登录则显示 X,否则显示 Y)。问题是 HTML 不传达范围层次结构。所以当你看到{{user.firstname + ' ' + user.lastname}}
你不知道变量user
来自哪里。第二个问题是子作用域可以隐藏根属性。与前面的示例一样,如果指令执行此操作scope.user = 'bla bla bla'
。它没有替换 rootScope 上的值。它隐藏了它。现在你在模板中得到了一些奇怪的意想不到的东西,你不知道为什么变量user
发生了变化。
相反,不要创建服务的唯一目的是存储和返回数据位。
Angular 的$cacheFactory
和$templateCache
是仅存在存储数据的服务的示例。我认为作者试图鼓励在 Angular 的module中使用常量和值,但这不是一个很好的描述。
所以我的疑问是为什么不建议将 $rootScope 用于函数作为全局函数?是否有任何性能问题?
$rootScope 是angular.config(..)
. 如果这是您唯一可以修改的时间,则可以在这段时间内修改范围。例如; 您可能需要在应用程序启动之前注入 API 密钥或 Google 分析变量。
任何作用域上的函数通常都是一个坏主意。主要是因为范围中的所有内容都在模板上的表达式中被消化。功能帐篷隐藏繁重的操作。无法通过调用函数时读取 HTML 来判断模板的重量。我见过作用域函数,例如getHeight()
函数本身执行 3 级嵌套循环。每次 angular 消化观察者以查看它是否发生变化时,都必须调用该函数。您应该尽量保持模板干燥。