Sou*_*ver 3 javascript arrays constructor derived-class es6-class
我有这个示例代码:
class TestClass extends Array {
constructor() {
console.log( 'constructor' );
let ar = [];
ar.push( { id: 1, name: 'a' } );
ar.push( { id: 2, name: 'b' } );
ar.push( { id: 3, name: 'c' } );
ar.push( { id: 4, name: 'd' } );
// finalizing object
super( ...ar );
}
Foo() {
console.log( 'foo' );
return this.filter( item => item.id > 2 );
}
}
let t = new TestClass();
console.log( t.Foo() );Run Code Online (Sandbox Code Playgroud)
这是我已经写的更简单的版本。我的应用程序运行到现在,但在我需要过滤扩展数组中的数据时停止了。我发现,问题是在我的类的对象上调用过滤器函数在内部调用构造函数。上面的代码显示了这个例子。有什么办法可以绕过这个问题,因为此时我无法再次调用构造函数。另外,我发现(使用这个简单的TestClass)实际输出不是我所期望的 - 我得到一个包含 4 个项目的数组,id 为 3、4、3、4。谁能解释这里发生了什么?
Symbol.species provides a way to return not another instance of the derived class but for .e.g. in this case an Array instance again.
class TestClass extends Array {
constructor() {
console.log( 'constructor' );
let ar = [];
ar.push( { id: 1, name: 'a' } );
ar.push( { id: 2, name: 'b' } );
ar.push( { id: 3, name: 'c' } );
ar.push( { id: 4, name: 'd' } );
// finalizing object
super( ...ar );
}
static get [Symbol.species]() { return Array; }
Foo() {
console.log( 'foo' );
return this.filter( item => item.id > 2 );
}
}
let t = new TestClass();
let a = t.Foo();
console.log('a : ', a);
console.log('(a instanceof Array) ? ', (a instanceof Array));
console.log('(a instanceof TestClass) ? ', (a instanceof TestClass));Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100%!important; top: 0; }Run Code Online (Sandbox Code Playgroud)
根据规范,
- 让 A 成为?ArraySpeciesCreate(O, 0)。
(这里O是原始数组和A结果)
- 让 C ? 获取(原始数组,“构造函数”)。
通俗地说,就是X.filter创建一个新对象并将X的构造函数应用于它。这就是为什么你的构造函数被再次调用的原因。
一般来说,这种设计需要固定。你的TestClassextends Array,现在,如果你在整个应用程序中替换Arraywith TestClass,它的行为会一样吗?显然不是,这意味着您TestClass 违反了基本的 OOP 原则,即所谓的 LSP,应该重新设计(例如,通过聚合数组而不是扩展数组)。