我一直在处理JavaScript中的可选参数,如下所示:
function myFunc(requiredArg, optionalArg){
optionalArg = optionalArg || 'defaultValue';
// Do stuff
}
有更好的方法吗?
这样使用||会失败吗?
我一直在处理JavaScript中的可选参数,如下所示:
function myFunc(requiredArg, optionalArg){
optionalArg = optionalArg || 'defaultValue';
// Do stuff
}
有更好的方法吗?
这样使用||会失败吗?
当前回答
在ECMAScript 2015(又名“ES6”)中,您可以在函数声明中声明默认参数值:
function myFunc(requiredArg, optionalArg = 'defaultValue') {
// do stuff
}
关于MDN的更多信息,请参阅本文。
目前只有Firefox支持这一点,但随着标准的完成,预计支持会迅速提高。
编辑(2019-06-12):
默认参数现在被现代浏览器广泛支持。所有版本的Internet Explorer都不支持此功能。然而,Chrome、Firefox和Edge目前都支持它。
其他回答
理想情况下,您可以进行重构以传递一个对象并将其与默认对象合并,因此传递参数的顺序无关紧要(请参阅下面的答案第二部分)。
然而,如果你只是想要一些快速、可靠、易于使用且体积不大的东西,请尝试一下:
对任意数量的默认参数的快速修复
它的伸缩性很好:每个新默认值的额外代码最少您可以将其粘贴到任何位置:只需更改所需参数和变量的数量如果您想将undefined传递给具有默认值的参数,那么这种方式会将变量设置为undefineed。此页面上的大多数其他选项将用默认值替换undefined。
下面是一个为三个可选参数(带有两个必需参数)提供默认值的示例
function myFunc( requiredA, requiredB, optionalA, optionalB, optionalC ) {
switch (arguments.length - 2) { // 2 is the number of required arguments
case 0: optionalA = 'Some default';
case 1: optionalB = 'Another default';
case 2: optionalC = 'Some other default';
// no breaks between cases: each case implies the next cases are also needed
}
}
简单的演示。这与roenving的答案类似,但很容易扩展到任意数量的默认参数,更容易更新,并且使用的参数不是Function.arguments。
传递和合并对象以提高灵活性
上面的代码和许多默认参数的方法一样,不能按顺序传递参数,例如,传递optionalC,但让optionalB返回默认值。
一个很好的选择是传递对象并与默认对象合并。这也有利于可维护性(只需注意保持代码可读,这样未来的合作者就不会对您传递的对象的可能内容进行猜测)。
使用jQuery的示例。如果不使用jQuery,可以改用Undercore的_.defaults(对象,默认值)或浏览以下选项:
function myFunc( args ) {
var defaults = {
optionalA: 'Some default',
optionalB: 'Another default',
optionalC: 'Some other default'
};
args = $.extend({}, defaults, args);
}
这是一个简单的例子。
function foo(requiredArg){
if(arguments.length>1) var optionalArg = arguments[1];
}
到达这个问题,在EcmaScript 2015中搜索默认参数,因此仅提及。。。
使用ES6,我们可以执行默认参数:
function doSomething(optionalParam = "defaultValue"){
console.log(optionalParam);//not required to check for falsy values
}
doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"
似乎最安全的方法-在决定使用默认值之前处理所有提供的错误类型的参数-是检查所调用函数中是否存在可选参数。
依赖于arguments对象成员创建(如果缺少参数,甚至不会创建),无论它可能被声明,我们都可以这样编写函数:
function myFunc(requiredArg, optionalArg){
optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
//do stuff
}
利用此行为:每当我们需要确保函数获得其过程中所需的某个值时,我们都可以安全地检查参数列表中的任何缺失值。
在下面的演示代码中,我们将故意将一个无类型和无值的undefined作为默认值,以便能够确定它是否会在错误的参数值(如0 false等)上失败,或者它的行为是否符合预期。
function argCheck( arg1, arg2, arg3 ){
arg1 = 0 in arguments || undefined;
arg2 = 1 in arguments || false;
arg3 = 2 in arguments || 0;
var arg4 = 3 in arguments || null;
console.log( arg1, arg2, arg3, arg4 )
}
现在,检查几个错误的参数值,看看是否正确检测到它们的存在,并因此计算为真:
argCheck( "", 0, false, null );
>> true true true true
这意味着-它们没有将/识别为预期的参数值。这里我们检查了所有参数的缺失,根据我们的算法,即使它们是假的,也应该获取它们的默认值。
argCheck( );
>> undefined false 0 null
如我们所见,参数arg1、arg2、arg3和未声明的arg4按顺序返回其确切的默认值。因为我们现在已经确定了它的有效性,所以我们可以重写函数,该函数实际上可以像第一个示例中那样使用它们,方法是使用if或三元条件。
对于具有多个可选参数的函数,-循环,可能会为我们节省一些时间。但是,由于如果不提供参数名称的值,则参数名称不会被初始化,因此即使我们以编程方式编写了默认值,我们也无法再通过名称访问它们,因此只能通过参数[索引]访问它们,这对代码的可读性来说是无用的。
但除了在某些编码情况下可能完全可以接受的这种不便之外,还有一个未知的问题,即多个任意数量的参数默认值。这可能也应该被认为是一个错误,因为我们不能再跳过参数,因为我们曾经可以在不提供值的情况下,使用如下语法:
argCheck("a",,22,{});
因为它会扔!这使得我们无法用所需默认值的特定错误类型替换参数。这是愚蠢的,因为arguments对象是一个类似数组的对象,并且应该支持这种语法和约定,无论是原生的还是默认的!
由于这个短视的决定,我们不能再希望编写这样的函数:
function argCheck( ) {
var _default = [undefined, 0, false, null ],
_arg = arguments;
for( var x in _default ) {
x in _arg ? 1 : _arg[x] = _default[x];
}
console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}
在这种情况下,我们将能够在arguments行中写入所需类型的每个默认值,并且至少能够通过args.index访问它们。
例如,此函数调用将产生:
argCheck();
>>undefined 0 false null
如我们的默认参数值数组中所定义的。但是,仍有可能出现以下情况:
argCheck({})
>>Object { } 0 false null
argCheck({}, [])
>>Object { } Array [ ] false null
但遗憾的是:
argCheck("a",,,22);
>>SyntaxError: expected expression, got ','
否则将记录:
>>a 0 false 22
但那是一个更好的世界!然而,对于最初的问题,最上面的函数会做得很好。例如。:
function argCheck( arg, opt ) {
1 in arguments ? 1 : opt = "default";
console.log( arg, opt );
}
p.s.:很抱歉,在编写参数输入时没有保留所选默认值的类型。
对undefined的测试是不必要的,也不像可能的那样健壮,因为正如user568458所指出的,如果通过null或false,则提供的解决方案将失败。API的用户可能认为false或null将强制方法避免该参数。
function PaulDixonSolution(required, optionalArg){
optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);
结果是:
defaultValue
provided
null
false
最后两个可能很糟糕。相反,请尝试:
function bulletproof(required, optionalArg){
optionalArg = optionalArg ? optionalArg : "defaultValue";;
console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);
结果是:
defaultValue
provided
defaultValue
defaultValue
唯一一个不理想的情况是,当您实际拥有布尔值或故意为空的可选参数时。