9 javascript inheritance class ecmascript-6
在es2015中,如果我有基类来表示List
如下所示:
class List {
constructor(data){
this.data = data
}
sortBy(attribute){
return this.data.sort((a,b) => {
return (a[attribute] < b[attribute]) ? 1 : -1;
})
}
get count() { return this.data.length }
}
Run Code Online (Sandbox Code Playgroud)
然后我可能想要用不太通用的数据子类化该基类,即,如果我是一个精灵,玩具:
class ToyList extends List {
constructor(toys){
super(toys);
this.toys = toys;
}
}
Run Code Online (Sandbox Code Playgroud)
除了这个名字,此时ToyList
没有什么不同List
.但是,如果你看的一个实例ToyList
,它有两个 data
及toys
属性.这些引用相同的数组,就概念化a的观点而言ToyList
,data
没有多大意义.
如果我做ToyList
,我都.data
和.toys
属性:
tl = new ToyList(['truck', 'plane', 'doll'])
Object { data: Array[3], toys: Array[3] }
Run Code Online (Sandbox Code Playgroud)
然后我tl
有一个data
和一个toys
属性.他们是同一个数组两个引用,但我想是的子类只具有toys
参考.
这是另一个在基类上使用方法的例子:
class Todos extends List {
constructor(todos){
super(todos);
this.todos = todos;
}
get byPriority(){
return this.todos.sortBy('priority')
}
}
var thingsToDo = [
{task: 'wash the dog', priority: 10},
{task: 'do taxes', priority: 1},
{task: 'clean the garage', priority: 0}
]
var todos = new Todos(thingsToDo);
todos.byPriority
Run Code Online (Sandbox Code Playgroud)
这样会很好,因为那样我就可以参考.byPriority
获取列表的排序版本,该版本非常特定于这种特定类型的数据.但是我看不出我怎么能做到这一点,因为
但我得到的是:
TypeError: this.todos.sortBy is not a function
Run Code Online (Sandbox Code Playgroud)
总而言之,我想要的是一种使用特定于子类语义的名称来引用基类属性的方法,而不会丢失基类的方法.
参考我们在评论中的讨论,更好的实现(imo),可扩展并避免您询问的问题
var AP = Array.prototype; //just lazy
class List {
constructor(elements){
for(var i = 0, j = (elements && elements.length)|0; i<j; ++i)
this[i] = elements[i];
//use length instead of count, stay compatible with the Array-methods
//will make your life easier
this.length = i;
}
length: 0
sortBy(attr){
return this.sort(function(a,b){
return (a[attribute] < b[attribute]) ? 1 : -1
});
}
//some functions have to be wrapped, to produce a List of the right type
filter(fn){
return new (this.constructor)(AP.filter.call(this, fn));
}
clone(){ return new (this.constructor)(this) }
}
//some functions can simply be copied from Array
//no need to re-implement or even wrap them.
List.prototype.sort = AP.sort;
List.prototype.push = AP.push;
List.prototype.pop = AP.pop;
Run Code Online (Sandbox Code Playgroud)
子类
class ToyList extends List {
constructor(toys){
//maybe you want to filter the input, before you pass it to the list
//or convert it, or whatever, it's all up to you
super(toys && AP.filter.call(toys, v=>v instanceof Toy));
}
//... additional functionality
}
Run Code Online (Sandbox Code Playgroud)
和一个示例用法
class Toy {
constructor(name){
this.name = name;
}
}
var a = new ToyList([
new Toy("foo"),
new Toy("bar"),
"not a toy",
new Toy("baz")
])
console.log(a instanceof ToyList, a);
var b = a.filter(toy => toy.name.charAt(0) === "b");
console.log(b instanceof ToyList, b);
Run Code Online (Sandbox Code Playgroud)
编辑:添加您的示例与待办事项
class Todos extends List {
//don't even need a constructor, since I simply want to pass
//the array to the parent-constructor
//don't use getter for functionality, use methods!
byPriority(){
return this.sortBy('priority');
}
}
var thingsToDo = [
{task: 'wash the dog', priority: 10},
{task: 'do taxes', priority: 1},
{task: 'clean the garage', priority: 0}
]
var todos = new Todos(thingsToDo);
todos.byPriority()
Run Code Online (Sandbox Code Playgroud)