命名空间提供的值很小

简介:   构建模块的指南  导出尽可能接近顶级  使用您导出的东西时,模块的消费者应尽可能少地摩擦。  添加太多级别的嵌套往往很麻烦,因此请仔细考虑如何构建事物。  从模块导出命名空间是添加太多嵌套层的示例。  虽然名称空间有时会有用,但在使用模块时会增加额外的间接级别。  这很快就会成为用户的痛点,而且通常是不必要的。  导出类上的静态方法也有类似的问题 - 类本身会添加一层嵌套。  除非以明显有用的方式增加表达性或意图,否则请考虑简单地导出辅助函数。  如果您只导出单个类或函数,请使用export default  正如"顶级附近的出口"减少了模块消费者的

  构建模块的指南

  导出尽可能接近顶级

  使用您导出的东西时,模块的消费者应尽可能少地摩擦。

  添加太多级别的嵌套往往很麻烦,因此请仔细考虑如何构建事物。

  从模块导出命名空间是添加太多嵌套层的示例。

  虽然名称空间有时会有用,但在使用模块时会增加额外的间接级别。

  这很快就会成为用户的痛点,而且通常是不必要的。

  导出类上的静态方法也有类似的问题 - 类本身会添加一层嵌套。

  除非以明显有用的方式增加表达性或意图,否则请考虑简单地导出辅助函数。

  如果您只导出单个类或函数,请使用export default

  正如"顶级附近的出口"减少了模块消费者的摩擦,引入默认导出也是如此。

  如果模块的主要用途是容纳一个特定的导出,那么您应该考虑将其导出为默认导出。

  这使导入和实际使用导入更容易一些。

  例如:

  MyClass.ts

  export default class SomeType {

  constructor() { ... }

  }

  MyFunc.ts

  export default function getThing() { return "thing"; }

  Consumer.ts

  import t from "./MyClass";

  import f from "./MyFunc";

  let x=new t();

  console.log(f());

  这对消费者来说是最佳的。

  他们可以根据需要命名您的类型(在这种情况下为t),并且不必进行任何过多的点击来查找对象。

  如果您要导出多个对象,请将它们全部放在顶层

  MyThings.ts

  export class SomeType { / ... / }

  export function someFunc() { / ... / }

  相反,导入时:

  明确列出导入的名称

  Consumer.ts

  import { SomeType, someFunc } from "./MyThings";

  let x=new SomeType();

  let y=someFunc();

  如果要导入大量内容,请使用命名空间导入模式

  MyLargeModule.ts

  export class Dog { ... }

  export class Cat { ... }

  export class Tree { ... }

  export class Flower { ... }

  Consumer.ts

  import * as myLargeModule from "./MyLargeModule.ts";

  let x=new myLargeModule.Dog();

  重新导出扩展延伸

  通常,您需要扩展模块的功能。

  一个常见的JS模式是使用扩展来扩充乐器大全列表,类似于JQuery扩展的工作方式。

  正如我们之前提到的,模块不像全局命名空间对象那样合并。

  建议的解决方案是不改变原始对象,而是导出提供新功能的新实体。

  考虑模块Calculator.ts中定义的简单计算器实现。

  该模块还导出一个辅助函数,通过传递输入字符串列表并在结尾写入结果来测试计算器功能。

  export class Calculator {

  private current=0;

  private memory=0;

  private operator: string;

  protected processDigit(digit: string, currentValue: number) {

  if (digit >="0" && digit <="9") {

  return currentValue * 10 + (digit.charCodeAt(0) - "0".charCodeAt(0));

  }

  }

  protected processOperator(operator: string) {

  if (["+", "-", "*", "/"].indexOf(operator) >=0) {

  return operator;

  }

  }

  protected evaluateOperator(operator: string, left: number, right: number): number {

  switch (this.operator) {

  case "+": return left + right;

  case "-": return left - right;

  case "": return left right;

  case "/": return left / right;

  }

  }

  private evaluate() {

  if (this.operator) {

  this.memory=this.evaluateOperator(this.operator, this.memory, this.current);

  }

  else {

  this.memory=this.current;

  }

  this.current=0;

  }

  public handleChar(char: string) {

  if (char==="=") {

  this.evaluate();

  return;

  }

  else {

  let value=thiscessDigit(char, this.current);

  if (value !==undefined) {

  this.current=value;

  return;

  }

  else {

  let value=thiscessOperator(char);

  if (value !==undefined) {

  this.evaluate();

  this.operator=value;

  return;

  }

  }

  }

  throw new Error(Unsupported input: '${char}');

  }

  public getResult() {

  return this.memory;

  }

  }

  export function test(c: Calculator, input: string) {

  for (let i=0; i < input.length; i++) {

  c.handleChar(input[i]);

  }

  console.log(result of '${input}' is '${c.getResult()}');

  }

  这是使用暴露测试功能的计算器的简单测试。

  import { Calculator, test } from "./Calculator";

  let c=new Calculator();

  test(c, "1+2*33/11="); // prints 9

  现在扩展这个以添加对10以外基数的输入的支持,让我们创建

  ProgrammerCalculator.tsProgrammerCalculator.ts

  import { Calculator } from "./Calculator";

  class ProgrammerCalculator extends Calculator {

  static digits=["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];

  constructor(public base: number) {

  super();

  const maxBase=ProgrammerCalculator.digits.length;

  if (base <=0 || base > maxBase) {

  throw new Error(base has to be within 0 to ${maxBase} inclusive.);

  }

  }

  protected processDigit(digit: string, currentValue: number) {

  if (ProgrammerCalculator.digits.indexOf(digit) >=0) {

  return currentValue * this.base + ProgrammerCalculator.digits.indexOf(digit);

  }

  }

  }

  // Export the new extended calculator as Calculator

  export { ProgrammerCalculator as Calculator };

  // Also, export the helper function

  export { test } from "./Calculator";

  新模块ProgrammerCalculator导出类似于原始Calculator模块的API形状,但不会扩充原始模块中的任何对象。

  这是我们的ProgrammerCalculator类的测试:

  TestProgrammerCalculator.ts

  import { Calculator, test } from "./ProgrammerCalculator";

  let c=new Calculator(2);

  test(c, "001+010="); // prints 3

  不要在模块中使用名称空间

  首次迁移到基于模块的组织时,常见的趋势是将导出包装在额外的命名空间层中。

  模块有自己的范围,只有模块外部才能看到导出的声明。

  考虑到这一点,在使用模块时,命名空间提供的值很小(如果有的话)。

  在组织方面,命名空间可以方便地将全局范围内与逻辑相关的对象和类型组合在一起。

  例如,在C#中,您将在System.Collections中找到所有集合类型。

  通过将我们的类型组织成分层命名空间,我们为这些类型的用户提供了良好的“发现”体验。

  另一方面,模块必然存在于文件系统中。

  我们必须通过路径和文件名来解决它们,因此我们可以使用逻辑组织方案。

  我们可以在 /collections/generic/文件夹中包含一个列表模块。

  命名空间对于避免在全局范围内命名冲突很重要。

  例如,您可能拥有

  My.Application.Customer.AddForm和

  My.Application.Order.AddForm - 两个具有相同名称但具有不同名称空间的类型。

  然而,这不是模块的问题。

  在一个模块中,没有合理的理由让两个具有相同名称的对象。

  从消费方面来看,任何给定模块的消费者都会选择他们用来引用模块的名称,因此不可能发生意外命名冲突。

  有关模块和命名空间的更多讨论,请参阅命名空间和模块。

  以下所有内容都是模块结构的红色标志。如果其中任何一个适用于您的文件,请仔细检查您是否尝试命名外部模块:

  1. 一个文件,其唯一的顶级声明是导出命名空间Foo {...}(删除Foo并将所有内容"向上移动"一个级别)

  2. 具有单个导出类或导出功能的文件(请考虑使用导出默认值)

  3. 具有相同export namespace Foo {的多个文件在顶层(不要认为这些将组合成一个Foo!)

目录
相关文章
|
2月前
不使用第三方变量的情况下交换两个数值
不使用第三方变量的情况下交换两个数值
23 1
|
2月前
|
C++
『C/C++』Eg4: 求自定类型元素的平均
『C/C++』Eg4: 求自定类型元素的平均
|
8月前
|
存储
2.1 CE修改器:精确数值扫描
本关是CE修改器的第一关,用户需要通过 `Cheat Engine` 工具完成精确扫描值。在这个练习中,需要将一个特定的数值(健康值)改变为 1000。首先,要确保数值类型设置正确,默认的是2字节或4字节。接着,选择“精确数值”扫描类型,将健康值填入数值输入框中,点击“首次扫描”。在扫描结果中,如果出现多个地址,可以继续点击打我按钮并输入变更后的健康值来进行“再次扫描”,确定正确的地址。双击左侧列表中的地址可以将其移动到下方的地址列表中并显示其当前值。接着,双击下方地址列表中的数值(或者选择它,按下回车),填写你要修改的数值1000。如果操作正确,"下一步"按钮将变成可点击的状态,本关就算完成
115 0
如何在把创建临时变量的前提下交换两个数(直接上代码)
如何在把创建临时变量的前提下交换两个数(直接上代码)
|
算法 Java
[算法] swap函数交换两个数值未改变问题解决
[算法] swap函数交换两个数值未改变问题解决
|
存储 Rust JavaScript
Rust:为什么不能在同一个结构体中存储一个值和对该值的引用?(修改版)
基本把下面问题这个搞明白,就能彻底明白 Rust 语言的生命周期是怎么回事了。简而言之,生命周期不会改变你的代码,是你的生命控制生命周期,而不是生命周期在控制你的代码。换言之,生命周期是描述性的,而不是规定性的。
151 0
|
C语言
用函数方法来比较三个数字中的较大值(常规,函数)
用函数方法来比较三个数字中的较大值(常规,函数)
110 0
用函数方法来比较三个数字中的较大值(常规,函数)
|
数据安全/隐私保护
CE修改器入门:精确数值扫描
附加`Tutorial-i386.exe进程`后,我们点击教程的下一步按钮,接着继续第二关,第二关的作用还是很简单的,主要目的是遍历出我们想要的动态数据,比如角色的生命,人物的魔法等,都会用到精确扫描,可以说这一关是既简单又实用的东西,也是今后制作中最常用的环节,接着我们看下`Tutorial-i386.exe程序`对这一关通关流程的描述:
223 0
CE修改器入门:精确数值扫描
|
算法 PHP
php关于数组n个随机数分成x组,使每组值相近的算法
php关于数组n个随机数分成x组,使每组值相近的算法
93 0
php关于数组n个随机数分成x组,使每组值相近的算法
lodash根据函数分配值,更新对象的属性路径的值
lodash根据函数分配值,更新对象的属性路径的值
63 0