2

How can i get an array of the arguments of a constructor class in JS? It's possible? Thanks in advance.

class Product {
    constructor(id, name, price, category, stock){
      this.id = id;
      this.name = name;
      this.price = price;
      this.category = category;
      this.stock = stock;
    }  
};

console.log(Product.constructor.params);

//expected output = ['id', 'name', 'price', 'category', 'stock'];

7
  • Without using type notation or a typed language like typescript? Commented Jul 10, 2021 at 22:04
  • i'm using typescript actually Commented Jul 10, 2021 at 22:07
  • Does this help? stackoverflow.com/questions/3404057/… Commented Jul 10, 2021 at 22:07
  • 2
    What are you trying to do? You already know the arity/arguments of your constructor, and the class properties. Commented Jul 10, 2021 at 22:09
  • I need to get the constructor arguments to compare and filter with another logic in my code Commented Jul 10, 2021 at 22:17

4 Answers 4

3
let s = Product.toString();
let params = s.substring(s.indexOf('(')+1, s.indexOf(')')).split(',')
Sign up to request clarification or add additional context in comments.

Comments

3

Inspired form @Porter answer and @evolutionxbox, I think that a reliable way would be using .match() like this:

class Product {
  constructor(id, name, price, category, stock, unusedArgument) {
    this.id = id;
    this.name = name;
    this.price = price;
    this.category = category;
    this.stock = stock;
  }
}

class Noarguments {
  constructor() {
  }
}

// A function
function getClassContructorParams(obj){
  let match = obj.toString().match(/constructor\((.+)\)/)
  
  if(match && match[1]){
    return match[1].split(",");
  }
  
  // If no match
  return []  
}


console.log(getClassContructorParams(Product))

/// Testing a class with no constructor arguments will return an empty array
console.log(getClassContructorParams(Noarguments))

My previous answer was returning the object properties, which may be different from the arguments used in the constructor...

Now using .match() will ensure what is returned really are the constructor arguments.

4 Comments

You don't need dummy arguments at all. Object.keys(new Product) produces the same result.
this only works if every argument has a one-to-one mapping to a property. What if any of the names of the arguments are different to the properties?
That works, i just would like to access the constructor arguments with no need to instance a new Product
@sonEtLumiere: I edited with something more accurate.
1

My point in the comments was it seems you're coming at this problem from the wrong direction. Maybe take this approach. Have an array of labels, and array of data, and pass those into the class. You'll still have the array of labels to access (and validate) in your other code, and everything will still work.

const labels = [ 'id', 'name', 'price', 'category', 'stock' ];

const data = [ 1, 'Bob', 100, 2, 1];

class Product {

    constructor(labels, data) {
      data.forEach((el, i) => this[labels[i]] = el);
    }
    
};

console.log(new Product(labels, data));
console.log(labels);

Or, if your products are identical in terms of properties you could just use an array of them, and use Object.keys to get the labels of the first object.

const data = [{ id: 1, name: 'Bob', price: 100, category: 2, stock: 1 }];
const labels = Object.keys(data[0]);

class Product {

    constructor(data) {
      for (let key in data) {
        this[key] = data[key];
      }
    }
    
};

console.log(new Product(data[0]));
console.log(labels);

Comments

0

There are some things to take into account:

  1. The presence of tabs, blank spaces or break lines.
  2. Parameters with default values

Look at the snippet(code) and read the comment lines; I tried to explain clearly each line of code.

class c1 {

  //the worst and ugliest code scenario
  constructor(id
    , innerHTML   , classes = "") {

    this.id=id
    this.innerHTML=innerHTML
    this.class=classes
    
  }

}

function getClassConstructorParameters(cr) {//class reference
  //get the params; it takes into account blanks spaces and line breaks
  let params = cr.toString().match(/\(([^\)]+)/)

  //remove all line breaks and blank spaces
  params = params[1].replace(/[\r\n\s]+/gm, "");

  //split the params
  params = params.split(',')

  //remove default values
  params = params.map((value, index, array) => {
    return value.split('=')[0];
  })
  return params

}

console.log(getClassConstructorParameters(c1))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.