&引用;方法重载“;在javascript中

&引用;方法重载“;在javascript中,javascript,overriding,Javascript,Overriding,所以我承认我是javascript新手,我来自C++背景(“嗨,我是Bob,我是基于类的静态语言用户”,合唱“嗨Bob!”) 我发现我经常以编写以下函数而告终: function someFunc() { if (arguments.length === 0 ){ ... } else { ... } } (可能有三种情况)。或者,我将差异写入名称: function someFuncDefault() { ... }; function s

所以我承认我是javascript新手,我来自C++背景(“嗨,我是Bob,我是基于类的静态语言用户”,合唱“嗨Bob!”)

我发现我经常以编写以下函数而告终:

function someFunc()
{
    if (arguments.length === 0 ){
       ...
    } else {
       ...
    }
}
(可能有三种情况)。或者,我将差异写入名称:

function someFuncDefault() { ... };
function someFuncRealArg(theArg) { ... };
(用“RealArg”代替一些语义上有内容的短语)


对于这类事情有更好的模式吗?

我不知道我会这样做,但它似乎会使代码稍微不那么难以管理:

function someFunc() {
    switch (arguments.length) {
        case 0: noArgs();
        case 1: oneArg(arguments[0]);
        case 2: twoArgs(arguments[0], arguments[1]);
    }
    function noArgs() {
        // ...
    }
    function oneArg(a) {
        // ...
    }
    function twoArgs(a, b) {
        // ...
    }
}
另一个例子可能是:

function someFunc(a, b) {
    if ('string' == typeof a) {
        // ...
    } else if ('number' == typeof a) {
        // ...
    }
}

当然,通过结合这两个示例(使用条件根据参数的数量和类型确定行为),您可能会创建一些非常难以管理的内容

在Javascript中,所有参数都是可选的

您可以尝试以下方法:

编辑(对于“truthiness”为false的值不中断的更好方法):

旧方法会因错误值而中断:

function foo(arg1, arg2) {
  if(!arg1) { set default }
  if(!arg2) { set default }
  //do stuff here
}

道格拉斯·克罗克福德(Douglas Crockford)的javascript讲座是一个很好的开始学习javascript的地方:

javascript让你在这方面变得非常懒惰(不像Python那么懒惰,但相当懒惰)


所以你真的不需要超负荷。Javascript不会因为传递了错误数量的参数而对您大喊大叫。

这是重载,而不是覆盖no

Javascript是弱类型的,因此方法签名和本机支持已过时。我的建议是传递一个可扩展对象作为单独的参数。根据需要检查和处理param对象上的属性的存在性

这比争论有什么好处?它可以让你明确你调用的地方的意图,明确你接收到的arg1和arg2的含义,并且它可以让你抽象到一个自定义的数据对象类,你可以扩展它的功能

function someFunc(params)
{
  var x = params.x || defaultX;
  var y = params.y || defaultY;

  //businesslogic
}

someFunc({x:'foo',y:'bar'});

someFunc({y:'baz'});

大家都很接近,我认为这里真正的问题是,在JavaScript中,您不应该根据传入的参数更改行为

由于JavaScript使所有参数都是可选的,因此您可以遵循使用此约定的简明方法:

function foo(bar, baz) {
    bar = bar || defaultBar;
    baz = baz || defaultBaz;
    .
    .
    .
}

就个人而言,我更喜欢编写将要执行的最复杂的函数,然后将其记录在注释中,以便其他人知道他们不需要发送所有参数

//concat(str1, str2 [,str3 [,str4 [,str5]]])
function concat(str1, str2, str3, str4, str5) {
    var str = str1 + str2;
    if(str3 != undefined)
        str += str3;
    if(str4 != undefined)
        str += str4;
    if(str5 != undefined)
        str += str5;
    return str;
}
我还发现,在正常函数中,参数顺序很重要,但有时我希望单独发送参数(即,我希望发送str3和str5,但不发送str4)。为此,我使用一个对象并测试已知的属性

//concat({str1:string, str2:string, str3:string, str4:string, str5:string})
//str3, str4, and str5 are optional
function concat(strngs) {
    var str = strngs.str1 + strngs.str2;
    if(strngs.str3 != undefined)
        str += strngs.str3;
    if(strngs.str4 != undefined)
        str += strngs.str4;
    if(strngs.str5 != undefined)
        str += strngs.str5;
    return str;
}

下面提供了一种更全面的过载机制:

调用重载函数:

notify('Simple sentence.'); 
// Output: 
// Simple sentence. 
notify(true, 'Greeting sentence.'); 
// Output: 
// Hello: Greeting sentence. 
notify(123); 
// JavaScript Error: 
// "No matching overload found." 


这不是一个方法重载的例子吗?我强烈推荐道格拉斯·克罗克福德的学习javascript的视频。。。它们帮助我真正理解了它们是如何结合在一起的:我以前从来都不知道参数数组。太棒了!我不知道如何处理示例中嵌套函数返回的值我不喜欢这样。。。这并没有真正解决他在代码库中的混乱问题,只是为他提供了一种不同的方法,让他拥有更多具有有趣名称的方法。@George:如果你想处理返回值,只需替换案例0:return oneArg(参数[0]);对于我现在所拥有的。@Akrikos:具有有趣名称的方法封装在定义函数中,不会使全局命名空间混乱。如果您担心在以这种方式设计的每个函数中都有一个noArgs()函数,请在它们前面加上前缀。。。someFunc_noArgs()。整洁!不是我推荐给初学者的东西(如果出了问题…),但是非常酷!在看了他的问题后,我认为这是他想做的最好的选择。否则他可能会尝试将方法附加到对象,但我认为在这种情况下,这对他没有帮助。我通常使用Grant Wagner方法,因为大多数接收变量参数的函数在每个参数组合中都有很多相同的代码。这种方法的一个潜在缺点是,您可能希望能够传递一些计算结果为false的东西(例如0)到您的函数。函数的类型可能更安全。是的……我本想提出警告,但在编写时忘记了:-(嗯……看起来我误解了这个问题。他已经在做类似的事情了。请纠正undefined的拼写错误。你检查'typeof'有什么原因,而不仅仅是使用===javascript保留词undefined?我的直觉告诉我,这是因为某些浏览器搞砸了javascript,没有将undefined定义为保留wo但我不知道这是怎么回事。但是,考虑一下这个例子——<代码> Type(PARAM.x)!=“未定义”?PARAM.x:Debug Trx;< /C> >更合适。
//concat({str1:string, str2:string, str3:string, str4:string, str5:string})
//str3, str4, and str5 are optional
function concat(strngs) {
    var str = strngs.str1 + strngs.str2;
    if(strngs.str3 != undefined)
        str += strngs.str3;
    if(strngs.str4 != undefined)
        str += strngs.str4;
    if(strngs.str5 != undefined)
        str += strngs.str5;
    return str;
}
var notify = new bob.fn.overloadFunction([ 
    { 
        condition: function(msg) { return bob.utils.isString(msg); }, 
        overload: function(msg) { 
            console.log(msg); 
        } 
    }, 
    { 
        condition: function(bSayHello) { return bob.utils.isBoolean(bSayHello); }, 
        overload: function(bSayHello, msg) { 
            msg = bSayHello ? 'Hello: ' + msg : msg; 
            console.log(msg); 
        } 
    } 
]); 
notify('Simple sentence.'); 
// Output: 
// Simple sentence. 
notify(true, 'Greeting sentence.'); 
// Output: 
// Hello: Greeting sentence. 
notify(123); 
// JavaScript Error: 
// "No matching overload found."