Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
161 views
in Technique[技术] by (71.8m points)

oop - Javascript: overriden methods defined as arrow functions are not seen in parent

I am using a parent class in my app to provide some basic functionality to its children. It looks roughly like this:

class Base {
  constructor(stream) {
    stream.subscribe(this.onData)
  }

  onData(data) {
    throw new Error('"onData" method must be implemented')
  }
}

class Child extends Base {
  onData(data) {
    // do stuff...
  }
}

That works fine and when I instantiate the Child, Base passes Child.onData to the stream The only problem is scope. In Child.onData I make a heavy use of other methods defined in child via this keyword. So when I pass this function as a callback to the stream, everything breaks. The evident solution is this:

class Base {
 constructor(stream) {
   stream.subscribe(this.onData)
 }

 onData = (data) => {
   throw new Error('"onData" method must be implemented')
 }
}

class Child extends Base {
 onData = (data) => {
   // do stuff...
 }
}

That does solve problems with scope, but now the function that is being passed to the stream is always Base.onData which throws errors. Generally, I could do something like passing the Child.onData to Base constructor. That would work, but what I would like to find is a more elegant solution to this, if it exists

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

That's why arrow functions in class properties are not that great. If you translate it to a normal ES6 class, this is what happens:

class Child extends Base {
  constructor(...args) {
    super(...args);
    this.onData = (data) => {
      // do stuff...
    };
  }
}

It's rather evident now why using the property inside the Base constructor doesn't work.

Instead, you should use normal method definitions and handle the context problem by binding the method inside the parent constructor:

class Base {
  constructor(stream) {
    if (this.onData == Base.prototype.onData)
      throw new Error('"onData" method must be overridden')
    this.onData = this.onData.bind(this);
    stream.subscribe(this.onData)
  }

  onData(data) {}
}

class Child extends Base {
  onData(data) {
    // do stuff...
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...