我已经看到了两种方法,用于确定参数是否已传递给JavaScript函数。我想知道是一种方法比另一种好,还是一种方法不好用?
function Test(argument1, argument2) {
if (Test.arguments.length == 1) argument2 = 'blah';
alert(argument2);
}
Test('test');
Or
function Test(argument1, argument2) {
argument2 = argument2 || 'blah';
alert(argument2);
}
Test('test');
据我所知,它们的结果是一样的,但我以前在生产中只使用过第一个。
Tom提到的另一个选择:
function Test(argument1, argument2) {
if(argument2 === null) {
argument2 = 'blah';
}
alert(argument2);
}
根据Juan的评论,Tom的建议最好改为:
function Test(argument1, argument2) {
if(argument2 === undefined) {
argument2 = 'blah';
}
alert(argument2);
}
有几种不同的方法来检查参数是否传递给了函数。除了你在你的(原始的)问题检查论点中提到的两个。长度或使用||操作符提供默认值-如果你是偏执狂,你也可以通过argument2 === undefined或typeof argument2 === 'undefined'显式检查参数是否为undefined(见注释)。
使用||操作符已经成为标准实践——所有很酷的孩子都这么做——但要小心:如果参数的计算结果为false,则会触发默认值,这意味着它实际上可能是未定义的、null、false、0,”(或任何Boolean(…)返回false的值)。
所以问题是什么时候使用哪种检查,因为它们产生的结果都略有不同。
检查参数。长度表现出“最正确”的行为,但如果有多个可选参数,它可能就不可行了。
对于undefined的测试是下一个“最好”的测试——只有当函数显式地使用一个未定义的值调用时,它才会“失败”,这很可能与省略实参一样。
使用||操作符可能会触发使用默认值,即使提供了有效参数。另一方面,它的行为实际上可能是需要的。
总结一下:只有在你知道自己在做什么的时候才使用它!
在我看来,使用||也是一种方法,如果有多个可选参数,并且不想传递一个对象文字作为命名参数的变通方法。
另一种使用参数提供默认值的好方法。长度可以通过switch语句的标签来实现:
function test(requiredArg, optionalArg1, optionalArg2, optionalArg3) {
switch(arguments.length) {
case 1: optionalArg1 = 'default1';
case 2: optionalArg2 = 'default2';
case 3: optionalArg3 = 'default3';
case 4: break;
default: throw new Error('illegal argument count')
}
// do stuff
}
这样做的缺点是,程序员的意图(在视觉上)并不明显,而是使用“神奇的数字”;因此,它可能容易出错。
两者存在显著差异。让我们建立一些测试用例:
var unused; // value will be undefined
Test("test1", "some value");
Test("test2");
Test("test3", unused);
Test("test4", null);
Test("test5", 0);
Test("test6", "");
使用您描述的第一个方法,只有第二个测试将使用默认值。第二个方法将默认除第一个方法外的所有方法(因为JS将把undefined、null、0和""转换为布尔值false。如果您使用Tom的方法,那么只有第四个测试将使用默认的方法!
你选择哪种方法实际上取决于你的预期行为。如果参数2允许使用undefined以外的值,那么你可能需要对第一个参数进行一些更改;如果需要一个非零、非空、非空的值,那么第二种方法是理想的——实际上,它经常被用来快速地从考虑中消除如此广泛的值。
有时你想要undefined作为一个可能的参数,但你仍然有可能不传递参数的情况。在这种情况下,你可以使用参数。长度来检查传递了多少个参数。
// Throw error if the field is not matching our expectations
function testField(label, fieldValue, expectedValue) {
console.log(arguments) // Gives: [Arguments] { '0': 'id', '1': 1, '2': undefined }
if(arguments.length === 2) {
if(!fieldValue) {
throw new Error(`Field "${label}" must have a value`)
}
}
else if(expectedValue === undefined) {
if(fieldValue !== undefined) {
throw Error(`Field "${label}" must NOT have a value`)
}
}
// We stringify so our check works for objects as well
else {
if(JSON.stringify(fieldValue) !== JSON.stringify(expectedValue)) {
throw Error(`Field "${label}" must equal ${expectedValue} but was ${fieldValue}`)
}
}
}
testField('id', 12) ->传递,我们不希望id为空
testField('id', undefined, undefined) ->通过,我们希望id为undefined
testField('id', 12, undefined) ->错误,我们希望id是undefined
如果您正在使用jQuery,一个不错的选择(特别是对于复杂的情况)是使用jQuery的extend方法。
function foo(options) {
default_options = {
timeout : 1000,
callback : function(){},
some_number : 50,
some_text : "hello world"
};
options = $.extend({}, default_options, options);
}
如果你像这样调用函数:
foo({timeout : 500});
选项变量将是:
{
timeout : 500,
callback : function(){},
some_number : 50,
some_text : "hello world"
};