Function overloading in Javascript - Best practices

后端 未结 30 1520
难免孤独
难免孤独 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 04:10

    If I needed a function with two uses foo(x) and foo(x,y,z) which is the best / preferred way?

    The issue is that JavaScript does NOT natively support method overloading. So, if it sees/parses two or more functions with a same names it’ll just consider the last defined function and overwrite the previous ones.

    One of the way I think is suitable for most of the case is follows -

    Lets say you have method

    function foo(x)
    {
    } 
    

    Instead of overloading method which is not possible in javascript you can define a new method

    fooNew(x,y,z)
    {
    }
    

    and then modify the 1st function as follows -

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

    If you have many such overloaded methods consider using switch than just if-else statements.

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

    check this out. It is very cool. http://ejohn.org/blog/javascript-method-overloading/ Trick Javascript to allow you to do calls like this:

    var users = new Users();
    users.find(); // Finds all
    users.find("John"); // Finds users by name
    users.find("John", "Resig"); // Finds users by first and last name
    
    0 讨论(0)
  • 2020-11-22 04:11

    Here is an approach that allows real method overloading using parameter types, shown below:

    Func(new Point());
    Func(new Dimension());
    Func(new Dimension(), new Point());
    Func(0, 0, 0, 0);
    

    Edit (2018): Since this was written in 2011, the speed of direct method calls has greatly increased while the speed of overloaded methods have not.

    It is not an approach I would recommend, but it is a worthwhile thought exercise to think about how you can solve these types of problems.


    Here is a benchmark of the different approaches - https://jsperf.com/function-overloading. It shows that function overloading (taking types into account) can be around 13 times slower in Google Chrome's V8 as of 16.0(beta).

    As well as passing an object (i.e. {x: 0, y: 0}), one can also take the C approach when appropriate, naming the methods accordingly. For example, Vector.AddVector(vector), Vector.AddIntegers(x, y, z, ...) and Vector.AddArray(integerArray). You can look at C libraries, such as OpenGL for naming inspiration.

    Edit: I've added a benchmark for passing an object and testing for the object using both 'param' in arg and arg.hasOwnProperty('param'), and function overloading is much faster than passing an object and checking for properties (in this benchmark at least).

    From a design perspective, function overloading is only valid or logical if the overloaded parameters correspond to the same action. So it stands to reason that there ought to be an underlying method that is only concerned with specific details, otherwise that may indicate inappropriate design choices. So one could also resolve the use of function overloading by converting data to a respective object. Of course one must consider the scope of the problem as there's no need in making elaborate designs if your intention is just to print a name, but for the design of frameworks and libraries such thought is justified.

    My example comes from a Rectangle implementation - hence the mention of Dimension and Point. Perhaps Rectangle could add a GetRectangle() method to the Dimension and Point prototype, and then the function overloading issue is sorted. And what about primitives? Well, we have argument length, which is now a valid test since objects have a GetRectangle() method.

    function Dimension() {}
    function Point() {}
    
    var Util = {};
    
    Util.Redirect = function (args, func) {
      'use strict';
      var REDIRECT_ARGUMENT_COUNT = 2;
    
      if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
        return null;
      }
    
      for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
        var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
        var currentArgument = args[argsIndex];
        var currentType = arguments[i];
        if(typeof(currentType) === 'object') {
          currentType = currentType.constructor;
        }
        if(typeof(currentType) === 'number') {
          currentType = 'number';
        }
        if(typeof(currentType) === 'string' && currentType === '') {
          currentType = 'string';
        }
        if(typeof(currentType) === 'function') {
          if(!(currentArgument instanceof currentType)) {
            return null;
          }
        } else {
          if(typeof(currentArgument) !== currentType) {
            return null;
          }
        } 
      }
      return [func.apply(this, args)];
    }
    
    function FuncPoint(point) {}
    function FuncDimension(dimension) {}
    function FuncDimensionPoint(dimension, point) {}
    function FuncXYWidthHeight(x, y, width, height) { }
    
    function Func() {
      Util.Redirect(arguments, FuncPoint, Point);
      Util.Redirect(arguments, FuncDimension, Dimension);
      Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
      Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
    }
    
    Func(new Point());
    Func(new Dimension());
    Func(new Dimension(), new Point());
    Func(0, 0, 0, 0);
    
    0 讨论(0)
  • 2020-11-22 04:11

    The best way really depends on the function and the arguments. Each of your options is a good idea in different situations. I generally try these in the following order until one of them works:

    1. Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument.

    2. Using number of arguments. Similar to the last option but may work when #1 doesn't work.

    3. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names.

    4. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.

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

    There is no way to function overloading in javascript. So, I recommend like the following by typeof() method instead of multiple function to fake overloading.

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

    Good luck!

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

    There is no real function overloading in JavaScript since it allows to pass any number of parameters of any type. You have to check inside the function how many arguments have been passed and what type they are.

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