0

I'm new to ES6, still working/looking into it, I want to update my KUTE.js library to latest and greatest JavaScript standards.

I can basically create more functions, import them separately in index.js and index-lite.js but I wish I could make use of extend to have a more consistent and abstract code, plus I don't want to have twice of the same code.

A very simple example looks like this:

// main.js
export const tweens = []

// STANDARD FUNCTIONS
export function Tween(el,start,end,ops){
  this.el = el
  this.start = start
  this.end = end
  return {this.el,this.start,this.end,this.ops}
}
Tween.prototype = {
  start : function(){
    tweens.push(this)
  }
}
export function Render(tw){
  tw.el.style.width = `${tw.start + tw.end}px`
}
export function Update(){
  tweens.forEach(function(tw){
    Render(tw)
  })
}
// index-mini.js
import {Tween,Render,Update} from 'main.js'

// EXTENDED FUNCTIONS
export function TweenExtended(el,start,end,ops,extendingArgument){
  this.el = el
  this.start = start
  this.end = end

  // other stuff before returning the object
  this.extendingProperty = `${extendingArgument} Hello there!`;
  doSomeAction();

  return {this.el,this.start,this.end,this.ops}
}
TweenExtended.prototype = {
  start : function(){
    tweens.push(this)
  },
  stop : function(){
    const i = tweens.indexOf(this)
    if (i !== -1) { tweens.splice(i, 1)
  }
}
export function RenderExtended(tw,ops){
  const widthValue = `${tw.start + tw.end}px`
  tw.el.style.width = widthValue
  // take an extended action
  ops.update ? tw.el.innerHTML = widthValue
}
export function UpdateExtended(ops){
  tweens.forEach(function(tw){
    RenderExtended(tw,ops)
  })
}
// index.js
import {TweenExtended,RenderExtended,UpdateExtended} from 'main.js'

Now, looking at Bergi's answer I just can't figure out a way to write a valid version of the following

// main.js
// EXTENDED FUNCTIONS
export function TweenExtended extends Tween(el,start,end,ops,extendingArgument){
  // do what Tween does

  // do other other stuff before returning the object
  this.extendingProperty = `${extendingArgument} Hello there!`;
  doSomeAction();

  return {this.el,this.start,this.end,this.ops}
}
TweenExtended.prototype = {
  // only add the additional methods
  stop : function(){
    const i = tweens.indexOf(this)
    if (i !== -1) { tweens.splice(i, 1)
  }
}
export function RenderExtended extends Render(tw,ops){
  // do what parent functions does
  // now do the extended actions
  const widthValue = `${tw.start + tw.end}px`
  ops.update ? tw.el.innerHTML = widthValue
}
export function UpdateExtended extends Update(ops){
  // this probably needs to be rewritwen entirelly
  tweens.forEach(function(tw){
    RenderExtended(tw,ops)
  })
}
// index.js
import {TweenExtended,RenderExtended,UpdateExtended} from 'main.js'

Questions:

  • export function AExtended extends A, what is the correct syntax?
  • is it possible that the extended functions "merge" with their parent functions?
  • if I were to use classes, is it possible to do the "merger"?
  • if any of the above, can you please share some tip/sample/example?
thednp
  • 4,401
  • 4
  • 33
  • 45

1 Answers1

1

extends keyword applies to classes, not functions. While in your original code the object definition is syntactically a function, if you want to adapt this code to the ES6 standards, you'd have to switch to class syntax.

Basically:

class Tween {
  constructor(...args) {
    // whatever you want on instantiation
  }

  start() {
    // whatever it does
  }
}
...
class TweenExtended extends Tween {
  constructor(...args) {
    super(...args) // this calls the constructor of Tween
    // any additional initialization you want
  }

  stop() {
    // you can override the Tween method or leave it be
  }

  start() {
    // you can any new methods you want
  }
}

and then just

export default TweenExtended

or

export TweenExtended

I hope this helps.

Maciej B. Nowak
  • 1,180
  • 7
  • 19
  • Thank you. I didn't know functions can't extend. I will give this a try right away. – thednp Jan 10 '20 at 11:50
  • Please, is it possible to extend class methods as well just like the classes? I want to have 2 different versions of the `start()` method. – thednp Jan 10 '20 at 12:07
  • I'm not sure what you are asking. If you want to have a method `Tween.start()` implemented and then change it's implementation in a subclass `SubTween` (extending a `Tween` of course), then by all means - yes. If you want to define two different implementations of a method in one class (let's say `Tween.start(int)` and `Tween.start(str)`), also called method overloading, then JS does not natively support this. What you want to do is check either the type of the argument provided or the number of arguments inside the method itself and act accordingly. – Maciej B. Nowak Jan 10 '20 at 12:13
  • Simple, I want `Tween.start()` does a,b `TweenExtended.stat()` does a,b+c. – thednp Jan 10 '20 at 12:15
  • I have an idea, I think it's probably the right one, I will break the `start()` method code into other methods and import+call them where needed. – thednp Jan 10 '20 at 12:27
  • 1
    You can do that, or if you want to extend the functionality of the `Tween.start()` in `TweenExtended` you can implement a `TweenExtended.start()` with a call to it's parent method. Check this answer for hints how to do it: https://stackoverflow.com/questions/11854958/how-to-call-a-parent-method-from-child-class-in-javascript – Maciej B. Nowak Jan 10 '20 at 12:42