在子类中重命名父类属性

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,它有两个 datatoys属性.这些引用相同的数组,就概念化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)

总而言之,我想要的是一种使用特定于子类语义的名称来引用基类属性的方法,而不会丢失基类的方法.

Tho*_*mas 2

参考我们在评论中的讨论,更好的实现(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)