【问题标题】:What method should I use to count instances of subclasses in JavaScript?我应该使用什么方法来计算 JavaScript 中子类的实例?
【发布时间】:2018-07-30 20:08:47
【问题描述】:

我想实现一个计数器,它将为类(和子类)的每个实例生成一个唯一 ID。

目前我使用这个:

class Item {
	constructor(type) {
		this.constructor.counter = (this.constructor.counter || 0) + 1;
		this.type = type || "item";
		this._id = this.type + "_" + this.constructor.counter;
		console.log(this.id);
	}
			
	get id() {
		return this._id;
	}
}

class SubItem extends Item {
	constructor() {
		super("sub_item");
	}
}

var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"

你看到问题了吗?如果我通过首先实例化一个 SubItem 来做到这一点,那么每个都可以正常工作......但是当我首先实例化“母类”时,计数器就坏了。有没有办法解决这个问题?

我正在寻找的行为是:

var test1 = new Item(); // <- "item_1" 
var test2 = new Item(); // <- "item_2" 
var test3 = new Item(); // <- "item_3" 
var test4 = new Item(); // <- "item_4" 
var test5 = new SubItem(); // <- "sub_item_1" 
var test6 = new SubItem(); // <- "sub_item_2" 
var test7 = new Item(); // <- "item_5" 
var test8 = new Item(); // <- "item_6" 

【问题讨论】:

  • 我已编辑(现已删除)评论,您将我的答案直接放入您的问题中。如果该评论不正确,请将其编辑为您的问题或编辑您的问题以实际说明您的预期输出。您现在的答案是在不同的假设下运行的。
  • 为什么当前行为存在问题?我建议不要(ab)使用实例 UID 来区分子类。

标签: javascript class instance counter uniqueidentifier


【解决方案1】:

问题在于SubItem 上的counter 属性遮蔽Item 类上的counter 属性。因此,当以下行运行时:

this.constructor.counter = (this.constructor.counter || 0) + 1;

当第一个SubItem 被实例化时,被访问this.constructor.counterItem 上的counter,通过原型继承。但随后对this.constructor.counter 的赋值会直接在子项上分配给counter 属性。 (因此,SubItem 的进一步实例化将直接在 SubItem 上引用 counter 而不是父类)。

您可以通过hasOwnProperty 来检查counter 属性是否直接在构造函数上

class Item {
  constructor(type) {
    this.constructor.counter = ((this.constructor.hasOwnProperty('counter') && this.constructor.counter) || 0) + 1;
    this.type = type || "item";
    this._id = this.type + "_" + this.constructor.counter;
    console.log(this.id);
  }

  get id() {
    return this._id;
  }
}

class SubItem extends Item {
  constructor() {
    super("sub_item");
  }
}

var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"

【讨论】:

  • 这正是我想要的!我不完全理解您的解决方案是如何工作的。 hasOwnProperty 方法返回一个布尔值,&& 是一个逻辑运算符。我看不出这是如何返回自然数的?
  • 没关系...我在这里找到了答案:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
【解决方案2】:

我想我会简单地在父类和子类上初始化计数器。我有点犹豫,但我认为它更清晰并简化了构造函数中的代码。这也让子类控制起点(不是我认为这超级有用):

class Item {
	constructor(type) {
        this.constructor.counter++;
        this.type = type || "item";
		this._id = this.type + "_" + this.constructor.counter;
		console.log(this.id);
	}
			
	get id() {
		return this._id;
	}
}
Item.counter = 0 // initialize

class SubItem extends Item {
	constructor() {
        super("sub_item");
	}
}
SubItem.counter = 0 // initialize

var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"

【讨论】:

  • 此解决方案有效,但我正在努力使我的代码尽可能干燥...
【解决方案3】:

将唯一 ID 放在构造函数之外,并允许它被所有将增加它的类限定。

let INSTANCE_COUNT = 0;

class Item {
  constructor(type) {
    this.type = type || "item";
    this._id = `${this.type}_${INSTANCE_COUNT++}`;
    console.log(this.id);
  }

  get id() {
    return this._id;
  }
}

class SubItem extends Item {
  constructor() {
    super("sub_item");
  }
}

var test1 = new Item(); // <- "item_0"
var test2 = new Item(); // <- "item_1"
var test3 = new Item(); // <- "item_2"
var test4 = new Item(); // <- "item_3"
var test5 = new SubItem(); // <- "sub_item_4"
var test6 = new SubItem(); // <- "sub_item_5"
var test7 = new Item(); // <- "item_6"
var test8 = new Item(); // <- "item_7"

【讨论】:

  • 我正在寻找的行为是让“sub_item”从 1 开始计数,而不是跟随“mother class”计数器。如果我先实例化“sub_item”,一切都很好......当我首先实例化“item”类时,计数器会中断。
猜你喜欢
  • 2012-07-24
  • 2017-04-14
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多