当前位置:  开发笔记 > 编程语言 > 正文

如何最好地确定参数是否未发送到JavaScript函数

如何解决《如何最好地确定参数是否未发送到JavaScript函数》经验,为你挑选了6个好方法。

我现在已经看到了两种确定参数是否已传递给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或使用||运算符提供默认值 - 还可以显式检查undefinedvia 的参数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
}

这有一个缺点,即程序员的意图不是(视觉上)显而易见并且使用"魔术数字"; 因此可能容易出错.



1> Christoph..:

有几种不同的方法可以检查参数是否传递给函数.除了你在(原始)问题中提到的两个 - 检查arguments.length或使用||运算符提供默认值 - 还可以显式检查undefinedvia 的参数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
}

这有一个缺点,即程序员的意图不是(视觉上)显而易见并且使用"魔术数字"; 因此可能容易出错.


我会添加一个通知 - 但是生病的混蛋会做些什么呢?
你应该检查typeof argument2 ==="undefined",以防有人定义"undefined".
undefined是全局空间中的变量.在全局范围内查找该变量比在本地范围中的变量查找更慢.但最快的是使用typeof x ==="undefined"
有趣.另一方面,比较=== undefined可能比字符串比较快.我的测试似乎表明你是对的,但是:x === undefined需要~1.5x typeof x的时间==='undefined'
@Cristoph:看完你的评论后,我四处询问.我能够证明字符串比较肯定不是(仅)通过指针比较,因为比较一个巨大的字符串需要比一个小字符串更长.但是,比较两个巨大的字符串只有在它们是用连接构建的时候才真的很慢,但如果第二个字符串是从第一个字符串创建的,那么它真的很快.因此它可能通过指针测试然后逐字母测试工作所以,是的,我充满了废话:)感谢启发我...
@Juan:不可变的字符串并不意味着唯一的字符串,只有后者才意味着字符串相等和指针相等的等价; 将Java VM作为具有不可变的语言运行时的示例,但是 - 在一般情况下 - 非唯一字符串

2> Greg Tatum..:

如果你正在使用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"
};



3> dkretz..:

这是我找到测试的少数情况之一:

if(! argument2) {  

}

工作得非常好,并在句法上带有正确的含义.

(同时限制我不允许合法的空值argument2具有其他一些含义;但这确实令人困惑.)

编辑:

这是松散类型和强类型语言之间风格差异的一个很好的例子; 以及javascript在黑桃中提供的风格选项.

我个人的偏好(没有批评意味着其他偏好)是极简主义.代码越少,只要我一致和简洁,其他人就越不能理解正确推断我的意思.

这种偏好的一个含义是我不想 - 不要觉得它有用 - 堆积一堆类型依赖性测试.相反,我试图让代码意味着它的意思; 并仅测试我真正需要测试的内容.

我在其他一些人的代码中发现的一个加剧是需要弄清楚他们是否期望在更大的背景下实际遇到他们正在测试的案例.或者,如果他们试图测试所有可能的事情,那么他们就不会完全预测上下文.这意味着在我能够自信地重构或修改任何内容之前,我最终需要在两个方向上详尽地跟踪它们.我认为他们很可能已经进行了各种各样的测试,因为他们预见到需要他们的情况(这通常对我来说并不明显).

(我认为这些人使用动态语言的方式存在严重的缺点.人们常常不想放弃所有静态测试,最终伪造它.)

在将全面的ActionScript 3代码与优雅的javascript代码进行比较时,我最明显地看到了这一点.AS3可以是js的3或4倍,我怀疑的可靠性至少不会更好,只是因为编码决策的数量(3-4X).

如你所说,Shog9,YMMV.:d


我觉得它更冗长,更令人分心; 但这是个人喜好,我敢肯定.
@le dorfier:它还排除使用空字符串0和布尔值false.
如果parameter2是布尔值=== false,该怎么办?或函数{return false;}?

4> Shog9..:

存在显着差异.让我们设置一些测试用例:

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,那么你可能想要在第一个上有一些变化; 如果需要非零,非零,非空值,则第二种方法是理想的 - 实际上,它通常用于从考虑中快速消除如此宽范围的值.



5> Lamy..:
url = url === undefined ? location.href : url;



6> 小智..:

在ES6(ES2015)中,可以使用默认参数

function Test(arg1 = 'Hello', arg2 = 'World!'){
  alert(arg1 + ' ' +arg2);
}

Test('Hello', 'World!'); // Hello World!
Test('Hello'); // Hello World!
Test(); // Hello World!
推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有