Function overloading in Javascript - Best practices

后端 未结 30 1523
难免孤独
难免孤独 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:57

    I would like to share a useful example of overloaded-like approach.

    function Clear(control)
    {
      var o = typeof control !== "undefined" ? control : document.body;
      var children = o.childNodes;
      while (o.childNodes.length > 0)
        o.removeChild(o.firstChild);
    }
    

    Usage: Clear(); // Clears all the document

    Clear(myDiv); // Clears panel referenced by myDiv

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

    As this post already contains a lot of different solutions i thought i post another one.

    function onlyUnique(value, index, self) {
        return self.indexOf(value) === index;
    }
    
    function overload() {
       var functions = arguments;
       var nroffunctionsarguments = [arguments.length];
        for (var i = 0; i < arguments.length; i++) {
            nroffunctionsarguments[i] = arguments[i].length;
        }
        var unique = nroffunctionsarguments.filter(onlyUnique);
        if (unique.length === arguments.length) {
            return function () {
                var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
                return functions[indexoffunction].apply(this, arguments);
            }
        }
        else throw new TypeError("There are multiple functions with the same number of parameters");
    
    }
    

    this can be used as shown below:

    var createVector = overload(
            function (length) {
                return { x: length / 1.414, y: length / 1.414 };
            },
            function (a, b) {
                return { x: a, y: b };
            },
            function (a, b,c) {
                return { x: a, y: b, z:c};
            }
        );
    console.log(createVector(3, 4));
    console.log(createVector(3, 4,5));
    console.log(createVector(7.07));
    

    This solution is not perfect but i only want to demonstrate how it could be done.

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

    This is an old question but one that I think needs another entry (although I doubt anyone will read it). The use of Immediately Invoked Function Expressions (IIFE) can be used in conjunction with closures and inline functions to allow for function overloading. Consider the following (contrived) example:

    var foo;
    
    // original 'foo' definition
    foo = function(a) {
      console.log("a: " + a);
    }
    
    // define 'foo' to accept two arguments
    foo = (function() {
      // store a reference to the previous definition of 'foo'
      var old = foo;
    
      // use inline function so that you can refer to it internally
      return function newFoo(a,b) {
    
        // check that the arguments.length == the number of arguments 
        // defined for 'newFoo'
        if (arguments.length == newFoo.length) {
          console.log("a: " + a);
          console.log("b: " + b);
    
        // else if 'old' is a function, apply it to the arguments
        } else if (({}).toString.call(old) === '[object Function]') {
          old.apply(null, arguments);
        }
      }
    })();
    
    foo(1);
    > a: 1
    foo(1,2);
    > a: 1
    > b: 2
    foo(1,2,3)
    > a: 1
    

    In short, the use of the IIFE creates a local scope, allowing us to define the private variable old to store a reference to the initial definition of the function foo. This function then returns an inline function newFoo that logs the contents of both two arguments if it is passed exactly two arguments a and b or calls the old function if arguments.length !== 2. This pattern can be repeated any number of times to endow one variable with several different functional defitions.

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

    INTRODUCTION

    So far reading through so many answers would give anyone a headache. Anyone trying to know the concept would need to know the following prerequisites.

    Function overloading Definition, Function Length property, Function argument property

    Function overloading in its simplest form means that a function performs different tasks on the basis of number of arguments that are being passed to it. Notably the TASK1, TASK2 and TASK3 are highlighted below and are being performed on the basis of the number of arguments being passed to the same function 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
    

    NOTE - JS does not provide inbuilt ability of function overloading.

    Alternative

    John E Resig (creator of JS) has pointed out an alternative which uses the above prerequisites to achieve the ability to implement function overloading.

    The code below uses a straightforward but naive approach by using if-else or switch statement.

    • evaluates the argument-length property.
    • different values result in invocation of different functions.

    var ninja = {
      whatever: function() {
           switch (arguments.length) {
             case 0:
               /* do something */
               break;
             case 1:
               /* do something else */
               break;
             case 2:
               /* do yet something else */
               break;
           //and so on ...
        } 
      }
    }

    Another technique is much more clean and dynamic. The highlight of this technique is the addMethod generic function.

    • we define a function addMethod which is used to add different functions to an object with the same name but different functionalities.

    • below the addMethod function accepts three params object name object, function name name and the function that we want to be invoked fn.

    • Inside addMethod definition var old stores the reference to the previous function being stored by the help of closure - a protective bubble.

    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);
      };
    };

    • use debugger to understand the code flow.
    • below the addMethod adds three functions which when invoked using ninja.whatever(x) with the number of arguments x which can be anything i.e. either blank or one or more than one invokes different functions as defined while making use of the addMethod function.

    var ninja = {};
    debugger;
    
    
    addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });
    addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });
    addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });
    
    
    ninja.whatever();
    ninja.whatever(1,2);
    ninja.whatever(3);

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

    Function overloading in Javascript:

    Function overloading is the ability of a programming language to create multiple functions of the same name with different implementations. when an overloaded function is called it will run function a specific implementation of that function appropriate to the context of the call. This context is usually the amount of arguments is receives, and it allows one function call to behave differently depending on context.

    Javascript doesn't have built-in function overloading. However, this behaviour can be emulated in many ways. Here is a convenient simple one:

    function sayHi(a, b) {
      console.log('hi there ' + a);
      if (b) { console.log('and ' + b) } // if the parameter is present, execute the block
    }
    
    sayHi('Frank', 'Willem');

    In scenarios where you don't know how many arguments you will be getting you can use the rest operator which is three dots .... It will convert the remainder of the arguments into an array. Beware of browser compatibilty though. Here is an example:

    function foo (a, ...b) {
      console.log(b);
    }
    
    foo(1,2,3,4);
    foo(1,2);

    0 讨论(0)
  • 2020-11-22 04:01

    Something like this can be done for function overloading.

    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"
    });
    

    Source

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