在Javascript中伪造函数重载的最好方法是什么?

我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:

一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?


当前回答

对于你的用例,这是我用ES6解决它的方法(因为它已经是2017年底了):

const foo = (x, y, z) => {
  if (y && z) {
    // Do your foo(x, y, z); functionality
    return output;
  }
  // Do your foo(x); functionality
  return output;
}

显然,您可以将其用于任何数量的参数,并相应地更改条件语句。

其他回答

介绍

到目前为止,阅读这么多答案会让任何人感到头疼。任何试图了解这个概念的人都需要知道以下先决条件。

函数重载定义,函数长度属性,函数参数属性

最简单形式的函数重载意味着函数根据传递给它的参数数量执行不同的任务。值得注意的是TASK1, TASK2和TASK3在下面突出显示,它们是根据传递给同一个函数fooYo的参数数量来执行的。

// if we have a function defined below
function fooYo(){
     // do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things

fooYo();  // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3

请注意 JS不提供内置的函数重载功能。

替代

John E Resig (JS的创建者)指出了一种替代方法,它使用上述先决条件来实现函数重载的能力。

下面的代码通过使用if-else或switch语句使用了一种简单但简单的方法。

计算参数长度属性。 不同的值导致调用不同的函数。

Var ninja = { function() { 切换(arguments.length) { 例0: /*做某事*/ 打破; 案例1: /* do something else */ 打破; 案例2: /*做其他事情*/ 打破; //等等… } } }

另一种技术更加简洁和动态。这项技术的亮点是addMethod泛型函数。

我们定义了一个addMethod函数,它用于向一个对象添加不同的函数,这些函数具有相同的名称但不同的功能。 下面的addMethod函数接受三个参数:对象名称object,函数名称name和我们想要调用的函数fn。 在addMethod定义中,var old存储了对前一个函数的引用,该函数通过闭包(一个保护气泡)的帮助存储。

函数addMethod(对象,名称,fn) { Var old =对象[name]; 对象[name] = function(){ 如果(fn)。Length == arguments.length) 返回fn。应用(这个参数) Else if (typeof old == 'function') 返回旧。应用(这个参数); }; };

使用调试器来理解代码流。 下面的addMethod添加了三个函数,当使用ninja.whatever(x)调用时,参数x的数量可以是任何东西,即空白或一个或多个调用不同的函数定义,同时使用addMethod函数。

Var ninja = {}; 调试器; addMethod(ninja,'whatever',function(){console.log("我是那个提供了零参数的人")}); addMethod(ninja,'whatever',function(a){console.log("我是提供了一个参数的人")}); addMethod(ninja,'whatever',function(a,b){console.log("我是一个提供了两个参数的人")}); ninja.whatever (); ninja.whatever(1、2); ninja.whatever (3);

在javascript中没有办法实现函数重载。 因此,我推荐使用下面的by typeof()方法而不是 多重功能伪造过载。

function multiTypeFunc(param)
{
    if(typeof param == 'string') {
        alert("I got a string type parameter!!");
     }else if(typeof param == 'number') {
        alert("I got a number type parameter!!");
     }else if(typeof param == 'boolean') {
        alert("I got a boolean type parameter!!");
     }else if(typeof param == 'object') {
        alert("I got a object type parameter!!");
     }else{
        alert("error : the parameter is undefined or null!!");
     }
}

好运!

#转发模式=> JS重载的最佳实践 转到另一个函数,它的名字是由第3和第4点构建的:

使用参数数量 检查参数类型

window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

#应用于您的案例:

 function foo(...args){
          return window['foo_' + args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);

  }
   //------Assuming that `x` , `y` and `z` are String when calling `foo` . 
  
  /**-- for :  foo(x)*/
  function foo_1_string(){
  }
  /**-- for : foo(x,y,z) ---*/
  function foo_3_string_string_string(){
      
  }

#其他复杂样本:

      function foo(...args){
          return window['foo_'+args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);
       }

        /** one argument & this argument is string */
      function foo_1_string(){

      }
       //------------
       /** one argument & this argument is object */
      function foo_1_object(){

      }
      //----------
      /** two arguments & those arguments are both string */
      function foo_2_string_string(){

      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function foo_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }
     
       //--- And so on ....   

对于函数重载,可以这样做。

function addCSS(el, prop, val) {
  return {
    2: function() {
      // when two arguments are set
      // now prop is an oject
      for (var i in prop) {
          el.style[i] = prop[i];
      }
    },
    3: function() {
      // when three arguments are set
      el.style[prop] = val;
    }
    }[arguments.length]();
}
// usage
var el = document.getElementById("demo");
addCSS(el, "color", "blue");
addCSS(el, {
    "backgroundColor": "black",
  "padding": "10px"
});

不是每个人都知道可以在函数签名中直接进行解构赋值。

得益于此,您可以轻松地定义非常灵活的方法签名,恕我直言,这比Java方法重载更优越。

例子:

const myFunction = (({a, b, c}) => {
    console.log(a, b, c);
});

myFunction({a: 1, b: 2});
myFunction({a: 1, b: 2, c: 3});

您甚至不需要考虑参数的顺序,并且调用语句和目标方法签名之间具有命名一致性。

你也可以指定默认值:

const myFunction = (({a = 1, b = 2, c} = {}) => {
    console.log(a, b, c);
});