最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - In a js class what is the better way to call super passing all the arguments up to the parent class? - Stack Overfl

programmeradmin7浏览0评论

In JavaScript ES6 classes, what is the better approach to call a super on the constructor passing all the arguments to the parent class?

I came up with this model using the spread operator, are there any downsides to this approach?

class Parent {
  constructor(a, b, c){
    console.log("a:", a);
    console.log("b:", b);
    console.log("c:", c);
  }
}

class Child extends Parent {
  constructor(){
    super(...arguments);
    this.doMyStuff();
  }
}

let child = new Child("Param A", "Param B", "Param C")

In JavaScript ES6 classes, what is the better approach to call a super on the constructor passing all the arguments to the parent class?

I came up with this model using the spread operator, are there any downsides to this approach?

class Parent {
  constructor(a, b, c){
    console.log("a:", a);
    console.log("b:", b);
    console.log("c:", c);
  }
}

class Child extends Parent {
  constructor(){
    super(...arguments);
    this.doMyStuff();
  }
}

let child = new Child("Param A", "Param B", "Param C")
Share Improve this question edited Aug 20, 2015 at 7:09 CodingIntrigue 78.6k32 gold badges175 silver badges177 bronze badges asked Aug 20, 2015 at 7:01 cassiozencassiozen 1011 silver badge5 bronze badges 4
  • 5 "what is the better approach" assuming there is a better approach. Looks ok to me. – Cerbrus Commented Aug 20, 2015 at 7:04
  • regarding the child constructor: do you really want constructor() or shouldn't it better be constructor(a, b, c) like in Parent? – wero Commented Aug 20, 2015 at 7:11
  • 1 @wero: Doesn't really matter, but yes, it would be useful if the arity of the constructor were 3 rather than 0. – T.J. Crowder Commented Aug 20, 2015 at 7:14
  • 1 @wero: That's exactly the point: for brevity sake I don't want to declare all the acceptable parameters in the child class, and just push all the received parameter to the parent. – cassiozen Commented Aug 20, 2015 at 7:25
Add a ment  | 

3 Answers 3

Reset to default 5

Let's do that old Pros and Cons thing:

Pros

  1. If you change the number of arguments that Parent accepts, you don't have to change Child. You still have to change code using Parent or Child if the arguments change affects it, but Child is automatically updated.

  2. (Very weak.) Brevity.

Cons

  1. Loss of clarity. What are the arguments to Child? Mitigation: Documentation.

  2. Tools can't prompt you with the names of the Child arguments if they don't know what they are; if the idiom became widespread, tools might analyze the code and figure it out, but I don't think it's likely. You could mitigate that by declaring the arguments even if you don't use them, but then you lose Pro #1 above.

  3. The arity of Child (Child.length) is 0 when in effect it's 3. Again could be mitigated by declaring the args, but again you lose Pro #1.

Neutral

  1. To avoid potential performance issues with arguments, you need to be using strict mode (you're not in that code unless it's in a module). (Because strict mode does away with the link between arguments and the declared arguments.) But you should be using strict mode anyway. :-)

Side note: Bergi made the brilliant observation that you can avoid arguments by using "rest args" instead:

constructor(...args) {
    super(...args);
}

You could bine destructuring with default params. I'm currently doing it like that:

class Parent {
  constructor(args = {}){
  //destructure what you need here
    let {
        a = "default a", 
        b = "default b", 
        c = "default c"
    } = args
    this.a = a
    this.b = b
    this.c = c
  }
}

class Child extends Parent {
  constructor(args = {}){
    //pass args object
    super(args)
    //destructure what you need here
    let {
      d = "default d",
      e = "default e"
    } = args
    this.d = d
    this.e = e
  }
}

    let parent = new Parent({
        a: "Param A", 
        b: "Param B", 
        c: "Param C"
    })

    let child = new Child({
        a: "Param A", 
        e: "Param E",
        c: "Param C"
    })

    console.log(parent)

    console.log(child)

This way changes your object declaration a bit, since you allways passing variables as a single args object.

You may consider checking for type object though since it wont throw an error if you'll pass something else - instead it would just use default values. But i feel that should count as exprected behaivior.

In the same manner args = {} handles the no arguments case, but it's not striclty neccessary either, but a good habbit, if you'll for example accidently pull something from args later in non destructuring manner.

Here's a bin: JSBin

What do you win with the generic approach?

class Child extends Parent {
   constructor(a,b,c){
      super(a,b,c);
      this.doMyStuff();
   }
}

is no longer as your version but explicit in what it is expecting and passing on, and therefore easier to understand for the casual reader of your source code.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论