打字稿&角度设计 - 传递依赖关系的替代方法

时间:2015-08-04 09:41:32

标签: javascript angularjs typescript

你好TypeScript / Angularists!

TL; DR 我可以将角度依赖关系传递给TypeScript模块/类,以便这些依赖关系不会成为类对象的属性 - 相反,它们可以通过范围函数参数获得吗?

我知道在angular / typescript中声明事物的推荐方法是在TS模块中创建一个TS类并将其作为角度服务释放,因为:

  • 它不能是工厂(见this
  • 拥有模块
  • 是件好事
  • 一个类(与普通函数比较)可用于检查typescript
  • 中的编译时类型

这种方法的一个例子如下:

/// <reference path="../../project.d.ts" />

module project.core.services {

  export class UiRoutes {
    static $inject = ['$state'];

    constructor(private $state: angular.ui.IStateService) {
    }

    public reloadCurrentView(): void {
      this.$state.go(this.$state.current.name, this.$state.params, {
        reload: true
      });
    }
  }

}

project.core.CoreModule.service('UiRoutes', project.core.services.UiRoutes);

无论如何,这种方法存在一个很大的问题,那就是 - 我被迫将所有角度依赖关系传递给类构造函数以使它们成为对象属性(可在任何地方使用,而不是封装 - 因为如果对象是可访问的,则所有它都是属性是可访问的。)

作为替代方案,有Backbone.js + Require.js example

define(['jquery', 'use!backbone','models/model'], function($, Backbone, Model){

  View = Backbone.View.extend({
    //...
  });

  return new View();
});

其中,如您所见,jquery,backbone和一些内部资源可用,但它不会保存为对象属性 - 它可以通过范围获得。这是纯粹自然的JavaScript做事方式 - 通过范围函数参数传递信息。在这种情况下,您可以封装更多的东西,并且您的代码变得不那么冗长。而且,主要是,选择而不是被迫遵循唯一正确的规则是件好事。

现在我知道骨干与角度不同,而且DI与require.js完全不同,等等等等。

我想要的是一个示例(或只是一个设计),它允许我指定所有角度依赖关系并使它们可以被TypeScript模块/类访问,但不能使它们成为类对象的属性。这可以通过纯粹的AngularJS(没有TypeScript)来实现,因此它可能与TypeScript一起使用。

PS我很乐意提供更好的问题描述,如果不清楚的话(请评论)。我不是真的对像“你不想要的东西,但它适合我,试试这个”:)这样的答案感兴趣,如果答案是“不,那是不可能的”,而不是我很欣赏一个证据和/或原因。

1 个答案:

答案 0 :(得分:1)

  

因为如果对象可以访问,那么它的所有属性都是可访问的

从运行时的角度来看,这可能是正确的,但运行时视角并不是唯一重要的视角。如果您正在使用TypeScript并将注入的服务标记为private,那么除非他们是主动恶意的,否则没有人访问这些内容。并且非常好的是你的代码已经无法适应其自身运行时环境中的恶意攻击者(通常,想要使用你的应用程序的人可以注入任何Angular服务并用自己的服务覆盖其属性)。

因此,在这方面,最好的办法是不关心某个对象在某个地方发生的事情,而不是某个地方的封闭。

  

现在我知道骨干与角度不同,而且DI与require.js完全不同,等等等等。

要扩展“blah blah blah”,这里的一个相关区别是你的requirejs模块实际上是一个单例,而你的Angular类通常不是(大多数可能是控制器)。

我们需要回到对象与闭包的差异来理解为什么这很重要。如果您将对注入的服务拥有封闭隐私(因为编译时隐私因任何原因而不够好),那么您的对象的每个实例都需要自己的子机箱才能够访问那些封闭的值。

当对象的实例很多时,为对象的每个单个实例复制函数闭包会导致很大的性能损失。这是更多的分配,更多的内存压力,更多的时间用于清理GC中的内容,花费更多的时间在GC中进行标记或清扫或重新计数,更少的参考局部性,更低效的JIT等等。这就是为什么TypeScript和其他语言不能为您提供现成的脚注来制作基于闭包的类。

现在你说“但我的服务是一个单身人士!”而你是对的。单身人士可以写成这样的闭包:

module project.core.services {
  export function UiRoutes($state: angular.ui.IStateService) {
    function go() {
      $state.go(/* etc*/);
    }

    function other() { }
    function foo() { }

    return {
      go,
      other,
      foo
    }
  }
}