在 JavaScript 中扩展基本数组 class
Extend base Array class in JavaScript
我有一个扩展基本数组 class 的自定义数组 class。我有一个易于使用的自定义方法
export class ExampleArray extends Array {
includesThing(thing) {
...
return false
}
}
不过现有的方法有filter
、map
等return数组实例。我想用这些方法 return ExampleArray
的一个实例。
我可以找到这些方法的接口,但找不到它们的实现。如何调用父方法和 return 我的自定义 EampleArray?类似下面的内容
export class ExampleArray extends Array {
filter() {
result = Array.filter()
array = new ExampleArray()
array.push(...result)
return array
}
或者这是扩展数组以创建自定义数组的正确方法吗?
创建新的方法名过滤器,并在里面使用'super'关键字,像这样:super.filter(func)
您需要 隐藏 现有的 .filter
和 .map
以便在调用 ExampleArray
的实例时,您的 new 函数将被调用,而不是 Array.prototype
函数。在 ExampleArray
中,您可以访问 super.map
和 super.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()
);
请注意,还有其他数组方法 return 数组,包括 splice
、slice
和(实验性的)flat
和 flatMap
。如果你想让它们 return 自定义 class 实例化而不是默认的 Array
实例,请遵循相同的模式:隐藏 Array.prototype
函数名称,以及 return new ExampleArray
填充了 apply
ing Array.prototype
方法的结果:
<fnName>(...args) {
return new ExampleArray(
...super.<fnName>.apply(this, args)
);
}
您不需要重写或覆盖 Array 的任何方法。只要确保你有一个合适的构造函数。
之所以有效,是因为在 ES6 规范中 here(强调已添加):
9.4.2.3 ArraySpeciesCreate(originalArray, length)
...
Let C be Get(originalArray, "constructor"). ReturnIfAbrupt(C). If
IsConstructor(C) is true, then
...
这就是 Array.filter
用于创建新数组的方法 - 它获取原始对象的构造函数并使用它来构造过滤后的数组。
这是另一个答案的代码,删除了重新定义的过滤器和映射方法,没有它们,它的工作方式相同。此代码(使用 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 是设计可扩展的。
更简单的方法是创建将任何数组作为第一个参数的静态函数。
这样 Array 仍然可以扩展(功能方面)。此外,扩展 Array 令人困惑,并且无法在大型团队中扩展。每当传输数组时(例如 HTTP 请求中的 JSON),如果不加小心,构造函数也会丢失。
我有一个扩展基本数组 class 的自定义数组 class。我有一个易于使用的自定义方法
export class ExampleArray extends Array {
includesThing(thing) {
...
return false
}
}
不过现有的方法有filter
、map
等return数组实例。我想用这些方法 return ExampleArray
的一个实例。
我可以找到这些方法的接口,但找不到它们的实现。如何调用父方法和 return 我的自定义 EampleArray?类似下面的内容
export class ExampleArray extends Array {
filter() {
result = Array.filter()
array = new ExampleArray()
array.push(...result)
return array
}
或者这是扩展数组以创建自定义数组的正确方法吗?
创建新的方法名过滤器,并在里面使用'super'关键字,像这样:super.filter(func)
您需要 隐藏 现有的 .filter
和 .map
以便在调用 ExampleArray
的实例时,您的 new 函数将被调用,而不是 Array.prototype
函数。在 ExampleArray
中,您可以访问 super.map
和 super.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()
);
请注意,还有其他数组方法 return 数组,包括 splice
、slice
和(实验性的)flat
和 flatMap
。如果你想让它们 return 自定义 class 实例化而不是默认的 Array
实例,请遵循相同的模式:隐藏 Array.prototype
函数名称,以及 return new ExampleArray
填充了 apply
ing Array.prototype
方法的结果:
<fnName>(...args) {
return new ExampleArray(
...super.<fnName>.apply(this, args)
);
}
您不需要重写或覆盖 Array 的任何方法。只要确保你有一个合适的构造函数。
之所以有效,是因为在 ES6 规范中 here(强调已添加):
9.4.2.3 ArraySpeciesCreate(originalArray, length)
...
Let C be Get(originalArray, "constructor"). ReturnIfAbrupt(C). If IsConstructor(C) is true, then
...
这就是 Array.filter
用于创建新数组的方法 - 它获取原始对象的构造函数并使用它来构造过滤后的数组。
这是另一个答案的代码,删除了重新定义的过滤器和映射方法,没有它们,它的工作方式相同。此代码(使用 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 是设计可扩展的。
更简单的方法是创建将任何数组作为第一个参数的静态函数。
这样 Array 仍然可以扩展(功能方面)。此外,扩展 Array 令人困惑,并且无法在大型团队中扩展。每当传输数组时(例如 HTTP 请求中的 JSON),如果不加小心,构造函数也会丢失。