TypeScript Essential Notes 7 - Modules

Understanding the need for modules in Javascript lingers

理解 Javascript 中模块的需求仍然存在
lingers 徘徊

Global Namespace == BAD!

  • Encourages implicit sharing between components
  • Difficult to determine component boundaries
  • Difficult to determine component dependencies

affectionately nicknamed spaghetti code 亲切地昵称为意大利面条代码

This kind of coding practice produces something that is affectionately nicknamed spaghetti code, because your entire application just becomes one giant ball of intertwined threads交织在一起的线程, without any way of telling where one component ends and another begins.
这种编码实践产生了一种昵称为意大利面条式代码的东西,因为你的整个应用程序只是变成了一个相互交织的线程的线程的巨大球,没有任何方式告诉一个组件在哪里结束,另一个从哪里开始。

Modules

  • Encourage more explicit dependencies
  • Produce clear component boundaries

Given the absence of any JavaScript syntax prior to ECMAScript 2015 to support the modularization of code, the development community had to get creative and come up with a variety of design patterns to both encapsulate the inner workings of components and help organize growing code bases.
鉴于在 ECMAScript 2015 之前没有任何 JavaScript 语法来支持代码的模块化,开发社区必须发挥创造力并提出各种设计模式来封装组件的内部工作并帮助组织不断增长的代码库。

manuscript 手稿
transcript 字幕/成绩单

JavaScirpt Encapsulation Methods

  • Module Pattern/revealing Module Pattern
  • Namespaces
  • ECMAScript 2015 modules/module Loaders

Organizaing your code with namespaces

avoid naming collisions 避免命名冲突

any valid js variable name will do 任何有效的 js 变量名都可以

Any valid JavaScript variable name will do, for example. Or, if you’d like, you can add some periods to add a hierarchy of namespaces all at once.
例如,任何有效的 JavaScript 变量名都可以。 或者,如果您愿意,可以添加一些句点以一次性添加命名空间的层次结构。

the general rule of thumb that i follow is to import a type or a namespace if the namespace is very long or if you’re going to refer to it more than once or twice, as is the case in this example.
我遵循的一般经验法则是,如果命名空间很长,或者如果您要多次引用它,则导入类型或命名空间,如本例中的情况。

likewise 同样地

fully qualified name 完全限定名称

// Any valid JavaScript variable name will do, for example.
// Or, if you'd like, you can add some periods to add a hierarchy of namespaces all at once.
namespace TodoApp.Model {
  //需要export
  export interface Todo {
    id: number;
    name: string;
    state: TodoState;
  }
}

// 可以重复
namespace TodoApp.Model {
  export enum TodoState {
    New = 1,
    Active,
    Complete,
    Deleted,
  }
}

// 同一个文件也可以写多个命名空间
namespace DataAccess {
  // import 取别名
  import Model = TodoApp.Model;
  import Todo = TodoApp.Model.Todo;

  export interface ITodoService {
    add(todo: Todo): Todo;
    delete(todoId: number): void;
    getAll(): Todo[];
    getById(todoId: number): Todo;
  }
}

Using namespaces to encapsulate private members

immediately invoked function expression (IIFE)
function defineType() {} ();
(function defineType(){}) ();
get into the guts of sth. 进入…的核心
gut 肠子,内脏

var jQuery = {
  version: 1.9,
  fn: {},
};

(function defineType($) {
  // 此处$变量名就是jQuery,$也可以改成任意变量明
  if ($.version < 1.15) {
    throw "Plugin requires jQuery version 1.15+";
  }
  $.fn.myPlugin = function () {
    // ...
  };
})(jQuery);

用namespace封装私有成员:

// model.ts 文件
namespace TodoApp.Model {
  export interface Todo {
    id: number;
    name: string;
    state: TodoState;
  }

  export enum TodoState {
    New = 1,
    Active,
    Completed,
    Deleted,
  }
}

// DataAccess.ts 文件
namespace DataAccess {
  import Model = TodoApp.Model;
  import Todo = Model.Todo;
  
  // 从service里提取后放到这里,从而完成用namespace封装私有成员
  let _lastId = 0;
  function generateTodoId() {
    return (_lastId += 1);
  }

  export interface IToDoService {
    add(todo: Todo): Todo;
    delete(todoId: number): void;
    getAll(): Todo[];
    getById(todoId: number): Todo;
  }

  class TodoService implements IToDoService {
  //提取以下,放到上面
    //private static _lastId: number = 0;

    // get nextId() {
    //   return (_lastId += 1);
    // }

    constructor(private todos: Todo[]) {}

    add(todo: Todo) {
      todo.id = generateTodoId();
      this.todos.push(todo);
      return todo;
    }

    delete(todoId: number): void {
      var toDelete = this.getById(todoId);
      var deletedIndex = this.todos.indexOf(toDelete);
      this.todos.splice(deletedIndex, 1);
    }

    getAll(): Todo[] {
      var clone = JSON.stringify(this.todos);
      return JSON.parse(clone);
    }

    getById(todoId: number): Todo {
      var filtered = this.todos.filter((i) => i.id == todoId);

      if (filtered.length) {
        return filtered[0];
      }
      return null;
    }
  }
}

Understanding the difference between internal and external moudles

Switching from internal to external modules

Importing modules using CommonJS syntax

import Model = require(’./model’);

Importing modules using ECMAScript 2015 syntax

import * as Model from ‘./model’;

Loading external modules

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值