Javascript中的方法重载

Posted

技术标签:

【中文标题】Javascript中的方法重载【英文标题】:Method overloading in Javascript 【发布时间】:2012-09-23 13:26:47 【问题描述】:

我在我的 javascript 代码中使用如下方法重载。

function somefunction()

    //1st function


function somefunction(a)

   //2nd function


function somefunction(a,b)

   //3rd function


somefunction(); // function call goes here

我不明白的是,如果我调用 somefunction() javascript 应该调用 第一个函数,但问题是 javascript 实际上调用了第三个函数。这是为什么?如何调用第一个和第二个函数?这是什么原因?是否有适当的方法在 Javascript 中实现方法重载?行业标准是什么?

【问题讨论】:

你不能在 JavaScript 中做到这一点。定义一个函数,然后在其中有分支来涵盖各种参数组合。 那么如何在 javascript 中使用面向对象的实践? Javascript 确实可以处理未传递的变量。因此,只需创建一个接收 (a, b) 的函数并读取输入以确定您的执行路线。 @Dasun 哪些对象装饰做法? @Šime Vidas 方法重载 【参考方案1】:

JavaScript 不支持方法重载(如在 Java 中或类似的),您的第三个函数会覆盖之前的声明。

相反,它通过arguments object 支持可变参数。你可以这样做

function somefunction(a, b) 
    if (arguments.length == 0)  // a, b are undefined
        // 1st body
     else if (arguments.length == 1)  // b is undefined
        // 2nd body
     else if (arguments.length == 2)  // both have values
        // 3rd body
     // else throw new SyntaxError?

您也可以只检查typeof a == "undefined" 等,这将允许调用somefunction(undefined),其中arguments.length1。这可能允许使用各种参数更轻松地调用,例如当您有可能为空的变量时。

【讨论】:

如果只有一个参数传递给函数调用,我怎么知道它是哪个参数..?喜欢somefunction(something); @RohitSharma 如果只有一个,那就是第一个。 JavaScript 不支持命名参数,重要的是顺序。 那么,我怎样才能使第一个参数可选..? @RohitSharma 你不能。当然可以拨打someFunction(undefined, someValue) 只是为了清关...! :) 但是,jQuery 的 on() 方法如何适用于不同类型的参数使用。像.on('event','selector',callback).on('event',callback) 一样,我们不会在那里为可选参数传递 undefined ......!【参考方案2】:

JS 会将undefined 传递给任何未提供的参数。如果你想要重载之类的东西,你需要做类似下面的代码:

function someFunction(a, b) 
    if (typeof a === 'undefined') 
        // Do the 0-parameter logic
     else if (typeof b === 'undefined') 
        // Do the 1-parameter logic
     else 
        // Do the 2-parameter logic
    

【讨论】:

【参考方案3】:

您只是在每次新声明时擦除变量somefunction

这相当于

   window.somefunction = function(...
   window.somefunction = function(...
   window.somefunction = function(...

Javascript 不提供方法重载。

正确的方法是:

定义第三个函数并测试定义了哪些参数 只传递一个包含参数的对象(实际上并没有什么不同,但更简洁)

【讨论】:

这个答案是错误的。函数 somefunc() ;与 var somefunc = function() ; 进行比较作为证明,如果您稍后声明 function anotherFunction() window.somefunc(); 【参考方案4】:

您不能在 JavaScript 中重载方法。在 javascript 中,函数存储在变量中。全局变量存储在窗口对象上。每个对象只能有一个同名的属性(独占键哈希)。

您可以做的是定义具有最多参数的定义并检查传入了多少。

function Test(a, b, c)

    if(typeof a == 'undefined') 
    
        a = 1;
    

    if(typeof b == 'undefined') 
    
        b = "hi";
    

    if(typeof c == 'undefined') 
    
        c = Date.Now;
    

现在,如果我调用 Test(),它的行为就像我调用了 Test(1, "hi", Date.Now)

【讨论】:

【参考方案5】:

在 JavaScript 中没有真正的函数重载,因为它允许传递任意数量的任意类型的参数。最好的做法是制作一个函数 喜欢: 我的函数(选择)


// with opt = 'arg1':'a1','arg2':2, etc, then check your opt inside of the function

【讨论】:

【参考方案6】:

我试图为here 描述的这个问题开发一个优雅的解决方案。你可以找到演示here。用法如下:

var out = def(
    'int': function(a) 
        alert('Here is int '+a);
    ,

    'float': function(a) 
        alert('Here is float '+a);
    ,

    'string': function(a) 
        alert('Here is string '+a);
    ,

    'int,string': function(a, b) 
        alert('Here is an int '+a+' and a string '+b);
    ,
    'default': function(obj) 
        alert('Here is some other value '+ obj);
    

);

out('ten');
out(1);
out(2, 'robot');
out(2.5);
out(true);

用于实现此目的的方法:

var def = function(functions, parent) 
 return function() 
    var types = [];
    var args = [];
    eachArg(arguments, function(i, elem) 
        args.push(elem);
        types.push(whatis(elem));
    );
    if(functions.hasOwnProperty(types.join())) 
        return functions[types.join()].apply(parent, args);
     else 
        if (typeof functions === 'function')
            return functions.apply(parent, args);
        if (functions.hasOwnProperty('default'))
            return functions['default'].apply(parent, args);        
    
  ;
;

var eachArg = function(args, fn) 
 var i = 0;
 while (args.hasOwnProperty(i)) 
    if(fn !== undefined)
        fn(i, args[i]);
    i++;
 
 return i-1;
;

var whatis = function(val) 

 if(val === undefined)
    return 'undefined';
 if(val === null)
    return 'null';

 var type = typeof val;

 if(type === 'object') 
    if(val.hasOwnProperty('length') && val.hasOwnProperty('push'))
        return 'array';
    if(val.hasOwnProperty('getDate') && val.hasOwnProperty('toLocaleTimeString'))
        return 'date';
    if(val.hasOwnProperty('toExponential'))
        type = 'number';
    if(val.hasOwnProperty('substring') && val.hasOwnProperty('length'))
        return 'string';
 

 if(type === 'number') 
    if(val.toString().indexOf('.') > 0)
        return 'float';
    else
        return 'int';
 

 return type;
;

【讨论】:

【参考方案7】:

我不明白的是,如果我调用 somefunction() javascript 应该调用第一个函数,但问题是 javascript 实际上调用了第三个函数。

这是预期的行为。

为什么会这样?

问题在于 JavaScript 本身并不支持方法重载。因此,如果它看到/解析两个或多个同名函数,它只会考虑最后定义的函数并覆盖之前的函数。

这是为什么呢?如何调用第一个和第二个函数?这是什么原因?

我认为适合大多数情况的一种方式如下 -

假设你有方法

function foo(x)

 

您可以定义一个新方法

,而不是重载方法这在javascript中是不可能的
fooNew(x,y,z)


然后修改第一个函数如下-

function foo(x)

  if(arguments.length==2)
  
     return fooNew(arguments[0],  arguments[1]);
  
 

如果您有许多这样的重载方法,请考虑使用switch 而不仅仅是if-else 语句。

是否有适当的方法来进行方法重载?行业标准是什么?

在 javascript 中没有这样的标准或更成熟的方法来进行方法重载。应该做最适合他们的编程设计的事情。 我想说简单地打开参数长度并检查类型是否未定义就足够了。

【讨论】:

【参考方案8】:

arguments 对象用于创建类似概念的方法重载。

参数是一种特殊类型的对象,仅在函数执行上下文中可用。

arguments.length属性用于标识传入函数的参数个数。

您可以更好地利用第一类函数来创建假方法重载。完整的概念在我自己的网站上进行了解释:Overload Functions in JavaScript

【讨论】:

您好,请记得在分享链接时披露您与您网站的连接! Tyler 我已经在我的博文中解释了方法重载的概念。这就是为什么添加我的博客链接 是的,但您需要在您的回答中指出该网站是您的。【参考方案9】:

JavaScript 不直接支持方法重载。 这是一个示例,您可以如何实现与它非常相似的目标,如下所示:

function overloadMethod(object, name, fn)

            if(!object._overload)
            object._overload = ;
            

            if(!object._overload[name])
            object._overload[name] = ;
            

            if(!object._overload[name][fn.length])
            object._overload[name][fn.length] = fn;
            

              object[name] = function() 
                        if(this._overload[name][arguments.length])
                        return this._overload[name][arguments.length].apply(this, arguments);
              ;


function Students()
  overloadMethod(this, "find", function()
            // Find a student by name
  );

  overloadMethod(this, "find", function(first, last)
            // Find a student by first and last name
  );



var students = new Students();
students.find(); // Finds all
students.find("Rahul"); // Finds students by name
students.find("Rahul", "Mhatre"); // Finds users by first and last name

来源:source

【讨论】:

【参考方案10】:

如果你使用类,你会创建两个不同的类,它们具有相同的方法和不同的参数。然后,您可以使用扩展运算符和依赖注入来模拟重载行为。

class Foo
  method()
    console.log('hello from method foo')
  


class Bar
  method(name)
    console.log(`hello from method bar. Name is $name`) 
  


function MimicOverload(obj, options)
    obj.method(...options)  


const obj1 = new Foo()
const obj2 = new Bar()


MimicOverload(obj1,[])
MimicOverload(obj2,['overloaded'])

【讨论】:

【参考方案11】:

I tinkered with this 并且能够轻松地针对自定义类进行这项工作。

let overloadTest = overload(
    [String], function(value) 
        console.log('we got a string', value);
    ,
    [Number], function(value) 
        console.log('we got a number', value);
    ,
    [String, Number], function(s, n) 
        console.log('we got a string AND a number', s, n);
    
    [MyCustomClass], function(value) 
        console.log('we got a MyCustomClass instance', value);
    
);

有了这个overload 实现:

function overload(...overloads) 
    const f = function(...args) 
        let constructorArray = args.map(arg => arg.constructor);
        let implIndex = f.overloads.findIndex(sig => 
            return constructorArray.length === sig.length &&
                constructorArray.every((o,i) => o === sig[i])
            ;
        ) + 1;
        if (implIndex > 0 && typeof(f.overloads[implIndex]) === 'function') 
            return f.overloads[implIndex].apply(, args);
         else 
            const message = "There is no implementation that matches the provided arguments.";
            console.error(message, constructorArray);
            throw Error(message);
        
    ;
    f.overloads = overloads;
    return f;
;

这还不适用于实例方法。但是,它可以扩展。

此外,参数列表直接引用构造函数(而不是字符串),这意味着您可以根据需要扩展额外的验证 - 例如,确保每个参数类型实际上是 @987654325 处的函数/构造函数@ 时间。您还可以想象创建一个执行 DI 的 overload() 版本。

【讨论】:

【参考方案12】:

我认为这不能被认为是方法重载,但是使用一个函数来不同的参数组合是一种替代方法。函数的参数必须是一个对象。

function something(obj)
   if(obj.a != undefined)
      return a*a;
   
   if((obj.b != undefined)&&(obj.c != undefined))
      return b*c;
   

【讨论】:

以上是关于Javascript中的方法重载的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript基础12——js的方法重载

html-javascript前端页面刷新重载的方法汇总

如何在javascript中进行重载? [复制]

html-javascript前端页面刷新重载的方法汇总

关于Java中的方法重载

JavaScript案列002 函数重载