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

javascript - ES6 function parameter validation - Stack Overflow

programmeradmin1浏览0评论

I've read a great pattern of handling required function parameters on 2ality.

function throwIfMissing() {
    throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
    return mustBeProvided;
}

Is there any such nice and clean way to throw validation errors?

function throwIfInvalid(value) {
    const max = 10;
    const min = 5;

    if(value < min || value > max){
        throw new Error(`Value must be between ${min} ${max}`);
    }

    return value;
}

function foo(mustBeValid = throwIfInvalid()) {
    return mustBeValid;
}

Of course the throwIfInvalid() function does not work as expected. My question is if there is any trick to make it work.?

I've read a great pattern of handling required function parameters on 2ality.

function throwIfMissing() {
    throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
    return mustBeProvided;
}

Is there any such nice and clean way to throw validation errors?

function throwIfInvalid(value) {
    const max = 10;
    const min = 5;

    if(value < min || value > max){
        throw new Error(`Value must be between ${min} ${max}`);
    }

    return value;
}

function foo(mustBeValid = throwIfInvalid()) {
    return mustBeValid;
}

Of course the throwIfInvalid() function does not work as expected. My question is if there is any trick to make it work.?

Share Improve this question edited Jul 6, 2017 at 9:58 Adam asked Jul 6, 2017 at 9:53 AdamAdam 5,2632 gold badges33 silver badges62 bronze badges 4
  • 2 why doesnt that code work? – Naeem Shaikh Commented Jul 6, 2017 at 9:55
  • it seems perfectly fine to me, your question is not for stackoverflow but for the ments section in the website link you're provided.. – vsync Commented Jul 6, 2017 at 9:58
  • if your foo function expects some argument and it is missing, then your code will fail unless you are able to verify the parameter is as expected – vsync Commented Jul 6, 2017 at 10:00
  • Instead of abusing default parameters I would encourage you to use a Proxy along with an apply trap to achieve this kind of runtime type checks. – user6445533 Commented Jul 6, 2017 at 10:43
Add a ment  | 

3 Answers 3

Reset to default 5

Of course it doesnt work, i think you are misunderstanding how Default Parameters work.

When you write

function foo(mustBeProvided = throwIfMissing())

you are assigning the result of throwIfMissing to the parameter IF AND ONLY IF the parameter is undefined.

Meaning that if that parameter is provided then throwIfMissing is not called at all; it will never execute and will never check for the validity of your parameter.

That's why you can only use this "trick" to react to an undefined parameter, not to validate one.

--

Alternative Solution

Personally i would solve the problem with a simple solution

function checkRange(val, min, max) {
    if (val > max || val < min) {
        throw new Error();
    }
}

function foo(val) {
    checkRange(val, 5, 10);
    return val;
} 

You may argue that this is much less elegant but keep in mind that in this case you can reuse the validator with different values, you don't have to hardcode min and max.

If you are looking for an npm module you can try this one but i wouldn't go that far for a simple validation.

This trick is only good for a generalized error message, and cannot be forced to be specific to the function it was checking its parameters, since the parameters were never supplied in the first place.

Now, a lesson:

Consider this situation:

function missingArgument() {
    console.warn('Missing parameter');
}

function foo(bar = missingArgument()){
    return bar.value;
}

console.log( foo() ) // will throw an error since "bar" is not a value
console.log('end');  // never reach here

The above example will throw an error, but the trick with the missingArgument function isn't very helpful since it doesn't tells you imminently where was the problem at. You can pass a string which will give helpful information:

function missingArgument(name) {
  console.warn('Missing parameter in function:', name);
}

function foo(bar = missingArgument('foo')) {
  return bar.value;
}

console.log(foo()) // will throw an error since "bar" is not a value
console.log('end'); // never reach here

This can be solved in this manner:

function missingArgument() {
    console.warn('Missing parameter');
}

function foo(bar = missingArgument()){
    if( bar == undefined ) return 0;
    return bar.value;
}

console.log( foo() )
console.log('end');

Each function obviously does its own thing, so you must know what the function should do with the expected argument and what is the expected output of the function, and then tailor-make your protection at the beginning of it.

The foo function above is expecting an Object and then it tries to access the value key of that object, and since the parameter is undefined it will fail and your whole code chain will stop. This is mostly unwanted and can be avoided. Above example will only work if the Object has a value key, like so:

console.log( foo({value:1}) )

As the other answers have pointed out, in the example provided by you, the throwIfInvalid() will get triggered only when the argument has not been passed. So you can not use it the way you did in the next example.

However, if you must use something similar, I could only think of the following :

function isValidNumber(value, min = 5, max = 10) {
    if(isNaN(value) || value < min || value > max) {
        throw new Error(`Value must be a number between ${min} ${max}`);
    }

    return true;
}

function foo(mustBeValid, isValid = isValidNumber(mustBeValid)) {
    return mustBeValid;
}

try {
    // This will return '7'
    var bar = foo(7);
    
    // Showing the value in the screen
    document.write(bar);
    
    // This will throw an error
    bar = foo(1);
    
} catch (e) {
  document.write('<br><br>'+e);
}

However, I would rather just call a validation method at the start as a guard clause. Or you can also checkout Proxy:

https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#Validation

发布评论

评论列表(0)

  1. 暂无评论