我之前回答过这个问题,但你问这些问题很好。
$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()
这样的作用域函数,其中函数本身执行了三层嵌套循环。每次 Angular 执行观察程序并检查它是否更改时,必须调用该函数。您应该尽可能使您的模板保持干燥。
$scope.foo
,解释器将继续在$scope._proto_
指向的对象中搜索该成员(它恰好是父作用域,或者如果没有父作用域,则是rootScope),然后是该对象的_proto_
,等等。 由于这在JavaScript中非常常见,所有引擎都会对其进行大量优化,即使是长的原型链也不会显着减慢您的代码。 - Kevin Dreßler