1

I have created a JS class. Here is following code:

export default class Service {
    constructor(
        serviceId,
        serviceName,
        serviceDescription,
        serviceImageName,
        categoryId,
        servicePrice,
        currencyCode,
        acceptPayment,
        serviceDuration,
        multipleBookingPerSlot,
        mode,
        tzSupport,
        minOptionCount
    ) {
        try{
            this.id = serviceId;
            this.title = serviceName;
            this.subTitle = serviceDescription;
            this.imageUrl = serviceImageName;
            this.categoryId = categoryId;
            this.price = servicePrice;
            this.currencyCode = currencyCode;
            this.acceptPayment = acceptPayment;
            this.meetingDuration = serviceDuration;
            this.multipleBookingPerSlot = multipleBookingPerSlot;
            this.serviceName = serviceName;
            this.mode = mode;
            this.tzSupport = tzSupport;
            this.session = minOptionCount
        } catch(e){
            if(e instanceof ReferenceError){
                console.error("Service data missing.")
            }
        }

    }
}

My goal is whenever new object of Service creates like new Service('1') if any of key is missing code should throw error and stop execution. How can i achieve this?

2
  • if(arguments.length!=13){ return} Commented Apr 22, 2017 at 9:19
  • this.id=undefined; is completely valid and will not throw any error... Commented Apr 22, 2017 at 9:20

2 Answers 2

2

You won't get a ReferenceError if the caller doesn't supply enough arguments, you'll just see undefined in the parameters.

You have 13 parameters (which is far, far too many). You could do the brute-force thing:

if (arguments.length < 13) {
    throw new Error("Missing arguments");
}

Instead, though, I suggest using the builder pattern or an options object instead of 13 discrete parameters. More than three parameters is fairly hard to manage.

For instance, with an options object:

export default class Service {
    constructor(
        options
    ) {
        ["id", "title", "subTitle", "imageUrl", "categoryId", "price", "currencyCode",
        "acceptPayment", "meetingDuration", "multipleBookingPerSlot", "serviceName",
        "mode", "tzSupport", "session"].forEach(name => {
            if (!options.hasOwnProperty(name)) {
                throw new Error(name + " is a required option");
            }
        });
        Object.assign(this, options);
    }
}

Usage:

let s = new Service({id: 1, title: "foo", /*...etc...*/});

That way, the caller isn't lost in a sea of parameters.


However, if it's important to validate the parameter values are present, isn't it important to validate their values, too? Nothing's to stop me from calling new Service with 13 completely-invalid arguments (undefined repeated 13 times, for instance).

So I would probably use an options object (because it's much easier for the caller) combined with parameter destructuring, and then individual validation, e.g.:

export default class Service {
    constructor({                 // <== Notice the {
        id,
        name,
        decription,
        imageUrl,
        categoryId,
        price,
        currencyCode,
        acceptPayment,
        meetingDuration,
        multipleBookingPerSlot,
        mode,
        tzSupport,
        minOptionCount
    }) {                          // <== And the }
        this.id = validate.positiveNumber(id);
        this.title = validate.nonBlank(name);
        this.subTitle = validate.nonBlank(description);
        this.imageUrl = validate.URL(imageUrl);
        this.categoryId = validate.positiveNumber(categoryId);
        this.price = validate.price(price);
        this.currencyCode = validate.currencyCode(currencyCode);
        this.acceptPayment = validate.boolean(acceptPayment);
        this.meetingDuration = validate.duration(meetingDuration);
        this.multipleBookingPerSlot = validate.boolean(multipleBookingPerSlot);
        this.serviceName = this.title; // Already validated
        this.mode = validate.mode(mode);
        this.tzSupport = validate.tzSupport(tzSupport);
        this.session = validate.whateverThisIs(minOptionCount);
    }
}

...where validate is a set of reusable validations. Usage is the same as above:

let s = new Service({id: 1, title: "foo", /*...etc...*/});
Sign up to request clarification or add additional context in comments.

1 Comment

TJ how can i use bulider pattern here?
0

As i already commented assigning undefined to an objects property is completely valid. The solution might be to check for the values of the arguments Arraylike against undefined:

constructor(a,b,c){
   if(arguments.length!=3){//check length
     return;
   }
   for(var a=0;a<arguments.length;a++){
      if(arguments[a]===undefined){//check against undefined
          return;
       }
    }
  //your code
}

http://jsbin.com/vugepakama/edit?console

2 Comments

What if 0, "", false, NaN, null, or undefined are valid values for one or more of the options?
!arguments[a] is true if argument is false, 0, '' etc

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.