ES6功能参数验证

时间:2017-07-06 09:53:55

标签: javascript design-patterns ecmascript-6

我已经在2ality上阅读了处理所需功能参数的绝佳模式。

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

有没有这样漂亮而干净的方法来抛出验证错误?

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;
}

当然throwIfInvalid()函数不能按预期工作。我的问题是,是否有任何技巧可以使其发挥作用。?

3 个答案:

答案 0 :(得分:2)

当然它不起作用,我认为你误解了Default Parameters的工作方式。

写作时

function foo(mustBeProvided = throwIfMissing())

您要将throwIfMissing的结果分配给参数 IF仅在参数为undefined

这意味着如果提供了该参数,则throwIfMissing 根本不会被调用;它永远不会执行,也永远不会检查参数的有效性。

这就是为什么你只能使用这个&#34;技巧&#34;对未定义的参数作出反应,而不是对其进行验证。

-

替代解决方案

我个人会用一个简单的解决方案解决问题

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

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

您可能会认为这不那么优雅,但请记住,在这种情况下,您可以重复使用具有不同值的验证器,您不必硬编码最小值和最大值。

如果您正在寻找一个npm模块,您可以尝试this one但我不会那么做以进行简单的验证。

答案 1 :(得分:1)

此技巧仅适用于通用错误消息,并且不能强制特定于检查其参数的函数,因为参数从未首先提供。

现在,上一课:

考虑这种情况:

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

上面的例子会抛出一个错误,但missingArgument函数的技巧并不是很有用,因为它不会立即告诉你问题在哪里。您可以传递一个字符串,该字符串将提供有用的信息:

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

这可以通过这种方式解决:

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

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

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

每个函数显然都有自己的功能,所以你必须知道函数应该对期望的参数做什么,函数的预期输出是什么,然后在它的开头定制你的保护。

上面的foo函数期待一个Object,然后它尝试访问该对象的value键,并且由于参数为undefined,它将失败并且整个代码链即将结束。这主要是不需要的,可以避免。 上面的示例仅在Object具有value键时才有效,如下所示:

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

答案 2 :(得分:0)

正如其他答案所指出的那样,在您提供的示例中,throwIfInvalid()仅在未传递参数时才会被触发。因此,您不能像在下一个示例中那样使用它。

但是,如果您必须使用类似的东西,我只会想到以下内容:

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);
}

但是,我宁愿只是在开始时将验证方法作为保护子句。或者,您也可以结帐Proxy

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