在javascript中使用Array子类中的.splice方法?

时间:2018-03-18 14:45:14

标签: javascript arrays subclass mutators

我正在尝试创建javascript的Array的子​​类。我想用array-type参数启动子类,并添加一个方法从数组(子类)中删除一个元素。

我的代码如下所示:

class CustomArray extends Array {
        
  constructor(array) {
    console.log('Initiating array:', array)
    super(...array);
  }

  remove(element) {
    let index = this.indexOf(element);
    if (index > -1) {
      return this.splice(index, 1);
    } 
    return [];
  }

}

var a = ['a', 'b', 'c', 'd', 'e'];

var list = new CustomArray(a)
console.log('list:', list);
console.log('remove:', list.remove('c'));
console.log('list:', list);

问题在于,当我调用.splice()时,它会从数组中删除元素,但也会返回已删除元素的数组,实际上它会返回我的子类CustomArray的新实例,该实例应该使用数组类型的参数启动,但是.splice()使用整数类型的参数启动它。

以下是我打电话给.splice()时的想法:

假设我们使用参数list启动了CustomArray类的实例['a','b','c','d','e'],然后我们调用方法list.remove('c')。 (就像在代码片段中一样) remove类的方法CustomArray检查c的索引是否在数组['a','b','c','d','e']中,2然后调用应删除1的method this.splice(2,1)数组['a','b','c','d','e']中索引2处的元素。方法splice删除元素c表单数组,但也返回类似new CustomArray(1)的内容,因为一个元素已从数组中删除,因此它尝试创建长度为1的数组,但由于类{{ 1}}是expectiong数组。

我想阻止CustomArray方法启动splice类的新实例,而是返回普通数组(Array对象的实例)。

Jsbin link.

2 个答案:

答案 0 :(得分:1)

  

我想阻止splice方法启动CostomArray类的新实例,而是返回普通数组(Array对象的实例)。

然后,您需要使用不同的名称创建不同的方法。 splice的语义为clearly and precisely defined;他们形成了Array类型的合同。让CostomArray违反合同意味着它不再是Array,而是类似,并且不应该延伸Array

由于您的方法被称为remove,这很好;如果您希望remove返回Array,而不是CostomArray,则只需要自己实施逻辑:

remove(element) {
  let index = this.indexOf(element);
  if (index > -1) {
    const newLength = this.length - 1;
    while (index < newLength) {
        this[index] = this[index + 1];
        ++index;
    }
    this.length = newLength;
    return [element];
  } 
  return [];
}

当然,当使用各种CostomArray方法调用时,使Array.prototype的构造函数正常工作。 (你在问题中的那个工作得很好,除了记录你不希望console.log的东西。)

答案 1 :(得分:0)

有可能splice返回一个标准数组-因此不用它调用构造函数。通过更改自定义类的@@species property,可以确定将使用哪个构造函数。但是请注意,这不仅会影响splice,还会影响会创建新实例的所有其他方法,包括mapfilter,{{1 }},...

您可以通过覆盖相应的静态getter来更改slice属性:

@@species