【问题标题】:Simpler way to use array of class使用类数组的更简单方法
【发布时间】:2019-10-16 06:19:13
【问题描述】:

我有一个类,然后定义了一个类的数组,每次想在数组中添加一个节点,我都不得不提到我不喜欢的类名:

export class ItemModel {
  constructor(
    ID,
    Name
  ) {
    this.ID = ID;
    this.Name = Name; 
  }
}

export var ItemsArray = [];

ItemsArray.push(new ItemModel(0, "BreakFast"));
ItemsArray.push(new ItemModel(1, "Lunch"));
ItemsArray.push(new ItemModel(2, "Dinner"));

看完这篇文章:

https://answers.unity.com/questions/637902/how-to-use-javascript-array-with-classes.html

我尝试在定义数组时声明类,如下所示:

var ItemsArray : ItemModel[];

但我收到错误:“类型只能在 .ts 文件中使用。

我在谷歌上搜索过,但没有一个有用。

任何建议都将不胜感激。

【问题讨论】:

  • javascript 的数组不是强类型的。您可以添加一个隐藏构造和推送的功能。
  • var PanelItemsArray : PanelItem[]; 是 TypeScript 语法,您需要一个 TypeScript 编译器才能将其转回 JavaScript。但即便如此,您也没有解决您的基本问题,因为即使在 TS 中您也需要执行 ItemsArray.push(new PanelItem(0, "BreakFast")); - 如果您的代码中有 ItemsArray.push(42);,那么所有 TS 都会为您提供错误,因为 42是一个数字,而不是 ItemModel
  • @T.J.Crowder,对不起,因为复制了我的部分源代码,我编辑了它

标签: javascript


【解决方案1】:

您链接到的帖子使用 TypeScript,这是一种与 JavaScript 不同的语言:它是 JavaScript 的超集(可编译为 JavaScript),添加了 静态类型(以及一对其他功能,例如构造函数中的自动属性初始化)。

此 TypeScript 行:

var ItemsArray : ItemModel[];

相当于这个JavaScript:

var ItemsArray;

只是TypeScript版本声明ItemsArray变量具有静态类型ItemModel[]

如果您使用 JavaScript 本身,则无需定义变量的类型。你的export var ItemsArray = []; 很好(除了我会使用letconst 而不是var)。


旁注:您可以使用 数组初始化器在 JavaScript 中更简洁地编写该数组:

export const ItemsArray = [
    new ItemModel(0, "BreakFast"),
    new ItemModel(1, "Lunch"),
    new ItemModel(2, "Dinner")
];

即使没有类型声明,这也是有效的 TypeScript:TypeScript 会推断您希望 ItemsArray 的类型为 ItemModel[](因为 TypeScript 确实是 type inference 并且它可以看到您正在填写 ItemsArray ItemModel 对象)。

如果你想从一个空数组开始但仍然给它一个静态类型,你可以这样做:

//                                   /------ Telling TypeScript to use ItemModel[]
//                      vvvvvvvvvvvvv        as the type
export const ItemsArray : ItemModel[] = [];
//                                   ^^^^^-- Initializing ItemsArray with an
//                                           empty array

然后你的 push 调用将被类型检查,所以这会工作:

ItemsArray.push(new ItemModel(0, "BreakFast"));

但这会导致错误(在 TypeScript->JavaScript 编译期间)

ItemsArray.push("BreakFast");

因为"Breakfast"ItemModel 不兼容。


旁注 2:JavaScript(和 TypeScript)中压倒性的约定是变量以小写字母开头,而不是大写字母。所以itemsArray 而不是ItemsArray

【讨论】:

  • 感谢您的评论,并对您的回答后的编辑表示抱歉,我在上面的示例代码的部分内容中错误地使用了 PanelItem,后来我将其更改为 ItemModel。你是对的,我使用的是反应类型脚本。我不能使用数组初始化器,因为节点将在用户操作后在运行时添加。
  • @albertsh - 我已经更新了答案以处理问题的变化(并且还解决了无法添加条目的问题,尽管这有点巧合:-) )。
  • 感谢您的时间和建议 ;)
【解决方案2】:

另一种选择是创建一个类来保存您的项目并创建一个方法来添加/删除它们。这样,您就不必每次都更新数组项。 ......好吧,你会的。 不必这样做,代码会。

class ItemModel {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
}

class ItemModelCollection {
  constructor() {
    this.items = [];
  }
  addItem(id, name) {
    if (Array.isArray(this.items)) {
      this.items.push(new ItemModel(id, name));
    }
  }
  removeItem(id) {
    if (Array.isArray(this.items)) {
      this.items = this.items.filter( i => i.id !== id);
    }
  }
}

const itemCollection = new ItemModelCollection();
document.getElementById('addItem').onclick = (e) => {
  const id = itemCollection.items.length; // obviously figure out a better id generator
  itemCollection.addItem(id, `Item Number ${id}`);
  console.log(itemCollection);
};
<button id="addItem">Add Item</button>

我还应该注意,不使用new ItemModel(id, name) 并使用提到的打字稿方式(<ItemModel>{ id: id, name: name}) 很好,但如果该类有方法,它们将无法工作,因为你没有“更新它”。如果你只是设置属性而不初始化类,你基本上失去了拥有类的意义。

pattner / 类问题的相关/解释(不像文章所说的那样具体角度):Angular : Class and Interface

【讨论】:

    猜你喜欢
    • 2015-12-03
    • 2022-08-23
    • 2013-02-10
    • 2014-03-12
    • 2019-03-02
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 2011-10-26
    相关资源
    最近更新 更多