Function overloading in Javascript - Best practices

后端 未结 30 1346
难免孤独
难免孤独 2020-11-22 03:33

What is the best way(s) to fake function overloading in Javascript?

I know it is not possible to overload functions in Javascript as in other languages. If I neede

相关标签:
30条回答
  • 2020-11-22 03:53

    The correct answer is THERE IS NO OVERLOADING IN JAVASCRIPT.

    Checking / Switching inside the function is not OVERLOADING.

    The concept of overloading: In some programming languages, function overloading or method overloading is the ability to create multiple methods of the same name with different implementations. Calls to an overloaded function will run a specific implementation of that function appropriate to the context of the call, allowing one function call to perform different tasks depending on context.

    For example, doTask() and doTask(object O) are overloaded methods. To call the latter, an object must be passed as a parameter, whereas the former does not require a parameter, and is called with an empty parameter field. A common error would be to assign a default value to the object in the second method, which would result in an ambiguous call error, as the compiler wouldn't know which of the two methods to use.

    https://en.wikipedia.org/wiki/Function_overloading

    All suggested implementations are great, but truth to be told, there is no native implementation for JavaScript.

    0 讨论(0)
  • 2020-11-22 03:54

    Another way to approach this is by using the special variable: arguments, this is an implementation:

    function sum() {
        var x = 0;
        for (var i = 0; i < arguments.length; ++i) {
            x += arguments[i];
        }
        return x;
    }
    

    so you can modify this code to:

    function sum(){
        var s = 0;
        if (typeof arguments[0] !== "undefined") s += arguments[0];
    .
    .
    .
        return s;
    }
    
    0 讨论(0)
  • 2020-11-22 03:54

    You can user the 'addMethod' from John Resig. With this method you can "overload" methods based on arguments count.

    // addMethod - By John Resig (MIT Licensed)
    function addMethod(object, name, fn){
        var old = object[ name ];
        object[ name ] = function(){
            if ( fn.length == arguments.length )
                return fn.apply( this, arguments );
            else if ( typeof old == 'function' )
                return old.apply( this, arguments );
        };
    }
    

    I have also created an alternative to this method that uses caching to hold the variations of the function. The differencies are described here

    // addMethod - By Stavros Ioannidis
    function addMethod(obj, name, fn) {
      obj[name] = obj[name] || function() {
        // get the cached method with arguments.length arguments
        var method = obj[name].cache[arguments.length];
    
        // if method exists call it 
        if ( !! method)
          return method.apply(this, arguments);
        else throw new Error("Wrong number of arguments");
      };
    
      // initialize obj[name].cache
      obj[name].cache = obj[name].cache || {};
    
      // Check if a method with the same number of arguments exists  
      if ( !! obj[name].cache[fn.length])
        throw new Error("Cannot define multiple '" + name +
          "' methods with the same number of arguments!");
    
      // cache the method with fn.length arguments
      obj[name].cache[fn.length] = function() {
        return fn.apply(this, arguments);
      };
    }
    
    0 讨论(0)
  • 2020-11-22 03:54

    For your use case, this is how I would tackle it with ES6 (since it's already the end of 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;
    }
    

    You can obviously adapt this to work with any amount of parameters and just change your conditional statements accordingly.

    0 讨论(0)
  • 2020-11-22 03:56

    I just tried this, maybe it suits your needs. Depending on the number of the arguments, you can access a different function. You initialize it the first time you call it. And the function map is hidden in the closure.

    TEST = {};
    
    TEST.multiFn = function(){
        // function map for our overloads
        var fnMap = {};
    
        fnMap[0] = function(){
            console.log("nothing here");
            return this;    //    support chaining
        }
    
        fnMap[1] = function(arg1){
            //    CODE here...
            console.log("1 arg: "+arg1);
            return this;
        };
    
        fnMap[2] = function(arg1, arg2){
            //    CODE here...
            console.log("2 args: "+arg1+", "+arg2);
            return this;
        };
    
        fnMap[3] = function(arg1,arg2,arg3){
            //    CODE here...
            console.log("3 args: "+arg1+", "+arg2+", "+arg3);
            return this;
        };
    
        console.log("multiFn is now initialized");
    
        //    redefine the function using the fnMap in the closure
        this.multiFn = function(){
            fnMap[arguments.length].apply(this, arguments);
            return this;
        };
    
        //    call the function since this code will only run once
        this.multiFn.apply(this, arguments);
    
        return this;    
    };
    

    Test it.

    TEST.multiFn("0")
        .multiFn()
        .multiFn("0","1","2");
    
    0 讨论(0)
  • 2020-11-22 03:57

    There are two ways you could approach this better:

    1. Pass a dictionary (associative array) if you want to leave a lot of flexibility

    2. Take an object as the argument and use prototype based inheritance to add flexibility.

    0 讨论(0)
提交回复
热议问题