我过去已经回答过这个问题,但你问这些问题很好。
$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 的模块中使用常量和值,但这并不是一个好的描述。
所以我的疑问是为什么不建议将 $rootScope 用作全局函数?有没有性能问题?
$rootScope 是angular.config(..)
. 如果这是您唯一可以修改的时间,则可以在此期间修改范围。例如; 您可能需要在应用启动之前注入 API 密钥或 Google 分析变量。
任何范围内的函数通常都是一个坏主意。主要是因为作用域中的所有内容都在模板上的表达式中被消化。隐藏繁重操作的功能。调用函数时无法通过读取 HTML 来判断模板的重量。我见过范围函数getHeight()
,比如函数本身执行 3 级嵌套循环的地方。每次 Angular 消化观察者以查看它是否已更改时,都必须调用该函数。您应该尽量保持模板干燥。