我现在已经看到了两种确定参数是否已传递给JavaScript函数的方法.我想知道一种方法是否优于另一种方法,或者一种方法是否使用不好?
function Test(argument1, argument2) { if (Test.arguments.length == 1) argument2 = 'blah'; alert(argument2); } Test('test');
要么
function Test(argument1, argument2) { argument2 = argument2 || 'blah'; alert(argument2); } Test('test');
据我所知,它们都产生了相同的结果,但我在生产之前只使用过第一个.
汤姆提到的另一个选择:
function Test(argument1, argument2) { if(argument2 === null) { argument2 = 'blah'; } alert(argument2); }
根据胡安的评论,将汤姆的建议改为:
function Test(argument1, argument2) { if(argument2 === undefined) { argument2 = 'blah'; } alert(argument2); }
Christoph.. 268
有几种不同的方法可以检查参数是否传递给函数.除了你在(原始)问题中提到的两个 - 检查arguments.length
或使用||
运算符提供默认值 - 还可以显式检查undefined
via 的参数argument2 === undefined
或者typeof argument2 === 'undefined'
是否是偏执(参见注释).
使用||
运营商已经成为标准做法-所有时尚的年轻人做到这一点-但要小心:如果参数的计算结果为默认值将被触发false
,这意味着它实际上可能是undefined
,null
,false
,0
,''
(或任何其他为它Boolean(...)
返回false
).
所以问题是何时使用哪种检查,因为它们都会产生略微不同的结果.
检查arguments.length
显示"最正确"的行为,但如果有多个可选参数则可能不可行.
接下来的测试undefined
是"最好的" - 如果用一个undefined
值显式调用函数,它只会'失败' ,在所有可能的情况下,应该以省略参数的方式对待它.
||
即使提供了有效参数,使用运算符也可能触发默认值的使用.另一方面,实际上可能需要它的行为.
总结一下:只有在你知道自己在做什么的时候才使用它!
在我看来,||
如果有多个可选参数,并且不希望将对象文字作为命名参数的变通方法传递,则使用也是一种方法.
arguments.length
通过掉落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 }
这有一个缺点,即程序员的意图不是(视觉上)显而易见并且使用"魔术数字"; 因此可能容易出错.
有几种不同的方法可以检查参数是否传递给函数.除了你在(原始)问题中提到的两个 - 检查arguments.length
或使用||
运算符提供默认值 - 还可以显式检查undefined
via 的参数argument2 === undefined
或者typeof argument2 === 'undefined'
是否是偏执(参见注释).
使用||
运营商已经成为标准做法-所有时尚的年轻人做到这一点-但要小心:如果参数的计算结果为默认值将被触发false
,这意味着它实际上可能是undefined
,null
,false
,0
,''
(或任何其他为它Boolean(...)
返回false
).
所以问题是何时使用哪种检查,因为它们都会产生略微不同的结果.
检查arguments.length
显示"最正确"的行为,但如果有多个可选参数则可能不可行.
接下来的测试undefined
是"最好的" - 如果用一个undefined
值显式调用函数,它只会'失败' ,在所有可能的情况下,应该以省略参数的方式对待它.
||
即使提供了有效参数,使用运算符也可能触发默认值的使用.另一方面,实际上可能需要它的行为.
总结一下:只有在你知道自己在做什么的时候才使用它!
在我看来,||
如果有多个可选参数,并且不希望将对象文字作为命名参数的变通方法传递,则使用也是一种方法.
arguments.length
通过掉落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 }
这有一个缺点,即程序员的意图不是(视觉上)显而易见并且使用"魔术数字"; 因此可能容易出错.
如果你正在使用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});
那么options变量将是:
{ timeout : 500, callback : function(){}, some_number : 50, some_text : "hello world" };
这是我找到测试的少数情况之一:
if(! argument2) { }
工作得非常好,并在句法上带有正确的含义.
(同时限制我不允许合法的空值argument2
具有其他一些含义;但这确实令人困惑.)
编辑:
这是松散类型和强类型语言之间风格差异的一个很好的例子; 以及javascript在黑桃中提供的风格选项.
我个人的偏好(没有批评意味着其他偏好)是极简主义.代码越少,只要我一致和简洁,其他人就越不能理解正确推断我的意思.
这种偏好的一个含义是我不想 - 不要觉得它有用 - 堆积一堆类型依赖性测试.相反,我试图让代码意味着它的意思; 并仅测试我真正需要测试的内容.
我在其他一些人的代码中发现的一个加剧是需要弄清楚他们是否期望在更大的背景下实际遇到他们正在测试的案例.或者,如果他们试图测试所有可能的事情,那么他们就不会完全预测上下文.这意味着在我能够自信地重构或修改任何内容之前,我最终需要在两个方向上详尽地跟踪它们.我认为他们很可能已经进行了各种各样的测试,因为他们预见到需要他们的情况(这通常对我来说并不明显).
(我认为这些人使用动态语言的方式存在严重的缺点.人们常常不想放弃所有静态测试,最终伪造它.)
在将全面的ActionScript 3代码与优雅的javascript代码进行比较时,我最明显地看到了这一点.AS3可以是js的3或4倍,我怀疑的可靠性至少不会更好,只是因为编码决策的数量(3-4X).
如你所说,Shog9,YMMV.:d
存在显着差异.让我们设置一些测试用例:
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
.如果你使用汤姆的方法,只有第四次试验将使用默认的!
您选择哪种方法实际上取决于您的预期行为.如果undefined
允许的值不是argument2
,那么你可能想要在第一个上有一些变化; 如果需要非零,非零,非空值,则第二种方法是理想的 - 实际上,它通常用于从考虑中快速消除如此宽范围的值.
url = url === undefined ? location.href : url;
在ES6(ES2015)中,可以使用默认参数
function Test(arg1 = 'Hello', arg2 = 'World!'){
alert(arg1 + ' ' +arg2);
}
Test('Hello', 'World!'); // Hello World!
Test('Hello'); // Hello World!
Test(); // Hello World!