扩展JavaScript中的基数组类

时间:2018-09-27 03:41:34

标签: javascript extend

我有一个自定义数组类,它扩展了基本数组类。我有一个易于使用的自定义方法

export class ExampleArray extends Array {
    includesThing(thing) {
        ...

        return false
    }
}

然而,filtermap等的现有方法返回一个数组实例。我想使用这些方法返回ExampleArray的实例。

我可以找到这些方法的接口,但找不到它们的实现。如何调用父方法并返回我的自定义EampleArray?类似于以下内容

export class ExampleArray extends Array {
    filter() {

    result = Array.filter()
    array = new ExampleArray()
    array.push(...result)

    return array
}

或者这甚至是扩展数组以创建自定义数组的正确方法吗?

4 个答案:

答案 0 :(得分:8)

您将需要阴影现有的.filter.map,以便在调用ExampleArray的实例时,您的函数,而不是Array.prototype函数。在ExampleArray内部,您可以访问super.mapsuper.filter以便进入Array.prototype方法。例如:

class ExampleArray extends Array {
  constructor(...args) {
    super(...args);
  }
  hasMoreThanTwoItems() {
    // example custom method
    return this.length > 2;
  }
  isExampleArray() {
    return true;
  }
  
  // Shadow Array.prototype methods:
  filter(...args) {
    return new ExampleArray(
      // Spread the result of the native .filter into a new ExampleArray instance:
      ...super.filter.apply(this, args)
    );
  }
  map(...args) {
    return new ExampleArray(
      ...super.map.apply(this, args)
    );
  }
}

const exampleArray = new ExampleArray(3, 4, 5, 6, 7);

// true, filtering will result in 3 items
console.log(
  exampleArray
    .filter(e => e > 4)
    .hasMoreThanTwoItems()
);

// false, filtering will result in zero items
console.log(
  exampleArray
    .filter(e => e > 10)
    .hasMoreThanTwoItems()
);

// true, is an ExampleArray
console.log(
  exampleArray
    .map(e => e * 2)
    .isExampleArray()
);

请注意,还有其他返回数组的Array方法,包括spliceslice和(实验的)flatflatMap。如果要让它们返回自定义类实例而不是默认的Array实例,请遵循相同的模式:对Array.prototype函数名进行阴影处理,并返回一个填充了{{ {1}}使用new ExampleArray方法:

apply

答案 1 :(得分:2)

您不需要重写或重写Array的任何方法。只需确保您具有适当的构造函数即可。

此方法有效的原因在于ES6规范here(强调):

  

9.4.2.3 ArraySpeciesCreate(originalArray,length)

     

...

     

让C为 Get(原始数组,“构造函数”)。 ReturnIfAbrupt(C)。如果   IsConstructor(C)为true,然后

     

...

这是Array.filter用于创建新数组的方法-它获取原始对象的构造函数,并使用它来构造过滤后的数组。

这是另一个答案中的代码,其中删除了重新定义的过滤器和map方法,并且在没有它们的情况下,其工作方式相同。这段代码(使用Chrome的控制台):

class ExampleArray extends Array {
  constructor(...args) {
    super(...args);
  }
  hasMoreThanTwoItems() {
    // example custom method
    return this.length > 2;
  }
  isExampleArray() {
    return true;
  }
}

const exampleArray = new ExampleArray(3, 4, 5, 6, 7);

// true, filtering will result in 3 items
console.log(
  exampleArray
    .filter(e => e > 4)
    .hasMoreThanTwoItems()
);

// false, filtering will result in zero items
console.log(
  exampleArray
    .filter(e => e > 10)
    .hasMoreThanTwoItems()
);

// true, is an ExampleArray
console.log(
  exampleArray
    .map(e => e * 2)
    .isExampleArray()
);

产生以下输出:

true
false
true

我必须补充,这通常不是扩展javascript类的好模型,但是显然,Array是可以通过设计扩展的。

答案 2 :(得分:0)

创建新的方法名称过滤器,并在内部使用“ super”关键字,例如:super.filter(func)

答案 3 :(得分:0)

更简单的方法是创建将任何数组作为第一个参数的静态函数。

这样,仍然可以扩展数组(在功能上)。此外,扩展Array会造成混乱,并且无法在大型团队中扩展。每当传输数组(例如HTTP请求中的JSON)时,构造函数也将丢失,而无需格外小心。