Function overloading in Javascript - Best practices [closed]
Asked Answered
J

37

909

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 needed a function with two uses foo(x) and foo(x,y,z) which is the best / preferred way:

  1. Using different names in the first place
  2. Using optional arguments like y = y || 'default'
  3. Using number of arguments
  4. Checking types of arguments
  5. Or how?
Jayson answered 19/1, 2009 at 0:6 Comment(5)
Perhaps it would be useful to ask why you think you need function overloading to begin with. I think that will get us closer to a real solution.Loreleilorelie
This is closed, but I do the following: this.selectBy = { instance: selectByInstance, // Function text: selectByText, // Function value: selectByValue // Function };Michi
My answer shows how to do run time function overloading, it has a speed penalty and I wouldn't advise doing it to get around Javascript's specification. Function overloading is really a compile time task, I only provide the answer for academic purposes and leave it up to your own discretion as to whether or not to employ it in code.Herminiahermione
Just in case it is useful, I've built a lightweight js framework that allows for type-based method overloading. Obviously the same caveats apply with regards to performance, but it's worked well for my needs so far and still has quite a lot of room for improvement: blog.pebbl.co.uk/2013/01/describejs.html#methodoverloadingWolgast
Closed because it's opinion based, and yet it has 871 upvotes. That means somethingValente
H
717

The best way to do function overloading with parameters is not to check the argument length or the types; checking the types will just make your code slow and you have the fun of Arrays, nulls, Objects, etc.

What most developers do is tack on an object as the last argument to their methods. This object can hold anything.

function foo(a, b, opts) {
  // ...
  if (opts['test']) { } //if test param exists, do something.. 
}


foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});

Then you can handle it anyway you want in your method. [Switch, if-else, etc.]

Hierogram answered 19/1, 2009 at 13:32 Comment(15)
Any suggestions on using this pattern with a callback? #9831527Ranchod
Could you provide a sample implementation of foo() that illustrates how these "opts" parameters are used/referenced?Pharmacist
Moe// It could be like this; if(opts['test']) //if test param exists, do something.. if(opts['bar']) //if bar param exists, do somethingChoosey
This isn't function overloading. Function overloading is having two separate functions with the same name but different parameters. What you're describing is just one function with an object argument at the end.Ostrich
@user1334007 it is impossible to have function overloading like you would do it in Java/.NET. Yes this is not "exactly" overloading, but it does the job.Hierogram
one thing is fine that js doesnt suports function overloading..thanx for dat clarityAdder
I'm surprised nobody has asked this already: why is checking arguments.length not recommended? Also, I've been here before and read What most developers do is..., but I'm sure this is the only place I've seen that done. That method also spoils the syntactic sugaryness of having 'overloads'!Dastard
@Dastard Yes you could check lengthm, but it would fail in causes like (obj, str, str) vs (obj, str, bool).Hierogram
@epascarello: ah, so there's no suggestion that arguments.length is a bad solution, just that in certain cases you'll have to fall back to checking types (which isn't ideal). Gotcha!Dastard
This makes it hard to document to the outside world what this function accepts as variables. I would not use this.Denten
@Denten You can not comment it or use JSDoc?Hierogram
Your options are you sniff types or you have an object with defined settings. Problem with types is any two the signatures can not be the same. jQuery does type sniffing with its methods.Hierogram
@Denten Using option objects is how a vast number of JS libraries do it-your (ahem) options are limited.Telescopy
"checking the types will just make your code slow" Relatively speaking, creating an object to then lookup properties in is far slower than type checking. If the object passed already exists then yes the property lookup on it will most likely be faster. jsperf.com/type-check-vs-property-lookup The code in this answer creates a new object with each call which is inherently slower than type checking.Kasiekask
one technique (which will deliberately except on unsupported types) is to have a thin wrapper around an object with type specific functions, using typeof parameter(s) as the key. eg var thing_handlers={ string : function(x){ return x;}, number : function(x) {return x+25; } }; function do_thing(x) {return thing_handlers[typeof x](x);} this is both fast, polymorphic, and most importantly, crashes at runtime to force developer to write safe(r) code.Burkey
B
196

I often do this:

C#:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

JavaScript Equivalent:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

This particular example is actually more elegant in javascript than C#. Parameters which are not specified are 'undefined' in javascript, which evaluates to false in an if statement. However, the function definition does not convey the information that p2 and p3 are optional. If you need a lot of overloading, jQuery has decided to use an object as the parameter, for example, jQuery.ajax(options). I agree with them that this is the most powerful and clearly documentable approach to overloading, but I rarely need more than one or two quick optional parameters.

EDIT: changed IF test per Ian's suggestion

Beady answered 15/2, 2012 at 17:19 Comment(13)
Parameters which are not specified are undefined in JS, not null. As a best practice, you should never set anything to undefined, so it should not be a problem as long as you change your test to p2 === undefined.Photogene
If you pass false as the last argument then it won't concatenate "false" to the end, because the if(p3) won't branch.Drosophila
Or the more popular typeof p2 === "undefined"Myocardium
Thanks for that! I too am familiar with the pattern you mentioned (used in various C family languages). Didn't work in javascript. Was looking for a fix. Your solution worked nicely! +1 :-)Touchback
Just a quick note, your typeof p2 === "undefined" is probably the reverse of what you're expecting in the instance of your example, I think typeof p2 !== "undefined" is what you intended. Also, May I suggest being its supposed to concatenate string, number, and boolean that you actually do p2 === "number"; p3 === "boolean"Trygve
you could use p2 !== void 0 for a less verbose comparisonTabb
I like doing this: p3 = p3 || 'default value';Denten
What is the meaning of === and !==? Why not just use == and !=?Centi
This could be improved with arguments, and a more modern approach could use rest params, concat and joinTerribly
Just a quick note to your C# code. Calling ToString is not needed when you concatenate objects using the concatenation operator (+).Haga
I think, this one should be an accepted answer. It is very straightforward to check for the arguments as undefined as opposed to passing an extra dummy object in the argument list.Hilaria
@Dorian, p3 = p3 || 'default value' isn't advised, because if you pass false as an intended value, then your false will be converted to your default value, should always test for undefined.Gastroenteritis
@TamzinBlake theoretically, you are right. pratically having "null" is already an issue in many languages. Having to deal with "null" and "undefined" at the same time is super annoying in javascriptFornication
A
119

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.

Amberambergris answered 19/1, 2009 at 0:12 Comment(4)
John Resig (of jQuery) once tried this, but the attempt was purely academic and didn't provide any real benefit.Idiotic
John Resig's function overload here ejohn.org/blog/javascript-method-overloadingSuperannuate
@Terrance: I like Resig's method too. It works like a charm. I just need to find a way to create a test for it to validate use cases.Abrahan
"This function won’t change the world, but it’s short, concise, and uses an obscure JavaScript feature – so it wins in my book." :-)Shiest
H
112

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.

Horick answered 3/11, 2015 at 18:21 Comment(5)
finally a normal answer! THERE IS NO OVERLOADING IN JAVASCRIPT.Warchaw
OP asked for a way to fake overloading.Brietta
As i did say before, we are here do educate people, we don't just give answers to them without verifying that what they are asking is right.Horick
Arguing with a human about the literal meaning when you should focus on the intended meaning is just as misplaced as arguing with a compiler about your intended meaning when it only responds to the literal meaning of your code. The OP's purpose was clearly to achieve a similar effect across call sites as overloading provides while acknowledging JS does not support the construct.Contaminate
Well 87 people upvoted, ao there's that. Emulate a feature like that is just a waste of time. You like it or not, JavaScript doesn't have this feature so people should know.Horick
L
27

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.

Luanaluanda answered 19/1, 2009 at 0:50 Comment(1)
this was my initial thought, however, if the function you are creating is to be used in a library or by others, enumerating the values plainly can be helpfulCodycoe
H
22

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);
Herminiahermione answered 26/12, 2011 at 12:13 Comment(0)
M
19

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.

Mountaintop answered 13/9, 2014 at 6:44 Comment(1)
yes at code editing time when we click on function definition it goes to correct definition BUT at run time overloaded function calls last function with that name and overwrites others previous ones with the same name irrespective of the argument numbers.Mismatch
S
17

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.

Szeged answered 19/1, 2009 at 1:30 Comment(0)
P
13

Not everybody knows that you can do Destructuring assignment directly in a function signature.

Thanks to that you can easily define a very flexible method signature, which is, IMHO, superior to Java method overloading.

Example:

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

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

You don't even need to respect the order of the parameters, and there is naming consistency between the calling statement and the target method signature.

You can also assign default values:

const myFunction = (({a = 1, b = 2, c} = {}) => {
    console.log(a, b, c);
});
Perfusion answered 1/6, 2021 at 7:55 Comment(2)
How would you go about defining function bodies for the concrete kind of input? Say you only have a and b, would you check whether or not c === undefined?Couldst
Yes, that's the only way. This approach does not represents a real function overloading, because in JavaScript you can have only one body for a named function. But at least it solves the hassle to have to write something like myFunction(undefined, undefined, myParameter) and also from checking the parameters order.Perfusion
S
11

I'm not sure about best practice, but here is how I do it:

/*
 * Object Constructor
 */
var foo = function(x) {
    this.x = x;
};

/*
 * Object Protoype
 */
foo.prototype = {
    /*
     * f is the name that is going to be used to call the various overloaded versions
     */
    f: function() {

        /*
         * Save 'this' in order to use it inside the overloaded functions
         * because there 'this' has a different meaning.
         */   
        var that = this;  

        /* 
         * Define three overloaded functions
         */
        var f1 = function(arg1) {
            console.log("f1 called with " + arg1);
            return arg1 + that.x;
        }

        var f2 = function(arg1, arg2) {
             console.log("f2 called with " + arg1 + " and " + arg2);
             return arg1 + arg2 + that.x;
        }

        var f3 = function(arg1) {
             console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
             return arg1[0] + arg1[1];
        }

        /*
         * Use the arguments array-like object to decide which function to execute when calling f(...)
         */
        if (arguments.length === 1 && !Array.isArray(arguments[0])) {
            return f1(arguments[0]);
        } else if (arguments.length === 2) {
            return f2(arguments[0], arguments[1]);
        } else if (arguments.length === 1 && Array.isArray(arguments[0])) {
            return f3(arguments[0]);
        }
    } 
}

/* 
 * Instantiate an object
 */
var obj = new foo("z");

/*
 * Call the overloaded functions using f(...)
 */
console.log(obj.f("x"));         // executes f1, returns "xz"
console.log(obj.f("x", "y"));    // executes f2, returns "xyz"
console.log(obj.f(["x", "y"]));  // executes f3, returns "xy"
Sextuplet answered 6/4, 2015 at 14:31 Comment(1)
@Luis : I've added some hopefully helpful comments.Sextuplet
A
7

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");
Abaxial answered 16/6, 2013 at 20:16 Comment(0)
S
7

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);
Shani answered 24/8, 2017 at 14:17 Comment(0)
W
5

Since JavaScript doesn't have function overload options object can be used instead. If there are one or two required arguments, it's better to keep them separate from the options object. Here is an example on how to use options object and populated values to default value in case if value was not passed in options object.

    function optionsObjectTest(x, y, opts) {
        opts = opts || {}; // default to an empty options object

        var stringValue = opts.stringValue || "string default value";
        var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
        var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

        return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

here is an example on how to use options object

Walton answered 9/1, 2014 at 2:30 Comment(0)
A
4

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!

Apian answered 1/12, 2011 at 9:1 Comment(3)
For God's sake! Use a switch statement!Offbeat
Also, if you insist of not using a switch, you should only call typeof once. var type = typeof param; if (type === 'string') ...Hendrickson
+1 to comment for the "===". The other advantage of the switch statement over if (...==...) is it's type-safe.Streaky
R
4

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
Ruskin answered 12/3, 2012 at 16:58 Comment(1)
Hi Jaider, check out my answer, it contains code for actual javascript method overloading. I'm talking Func(new Point()) and Func(new Rectangle()) will execute different functions. But I must point out that this is a dirty hack, since method overloading is really a compile time task not run time.Herminiahermione
N
4

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;
}
November answered 24/8, 2017 at 8:3 Comment(0)
S
3

#Forwarding Pattern => the best practice on JS overloading Forward to another function which name is built from the 3rd & 4th points :

  1. Using number of arguments
  2. Checking types of arguments
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

#Application on your case :

 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(){
      
  }

#Other Complex Sample :

      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 ....   
Sunda answered 19/7, 2016 at 8:18 Comment(0)
A
3

You can now do function overloading in ECMAScript 2018 without polyfills, checking var length/type, etc., just use the spread syntax.

function foo(var1, var2, opts){
  // set default values for parameters
  const defaultOpts = {
    a: [1,2,3],
    b: true,
    c: 0.3289,
    d: "str",
  }
  // merge default and passed-in parameters
  // defaultOpts must go first!
  const mergedOpts = {...defaultOpts, ...opts};

  // you can now refer to parameters like b as mergedOpts.b,
  // or just assign mergedOpts.b to b
  console.log(mergedOpts.a);
  console.log(mergedOpts.b);
  console.log(mergedOpts.c);  
  console.log(mergedOpts.d);
}
// the parameters you passed in override the default ones
// all JS types are supported: primitives, objects, arrays, functions, etc.
let var1, var2="random var";
foo(var1, var2, {a: [1,2], d: "differentString"});

// parameter values inside foo:
//a: [1,2]
//b: true
//c: 0.3289
//d: "differentString"

What is spread syntax?

The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object. More on mdn

Note: spread syntax in object literals doesn't work in Edge and IE and it is an experimental feature. see browser compatability

Arterialize answered 2/3, 2019 at 12:15 Comment(0)
C
2

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.

Cowgill answered 19/2, 2014 at 9:13 Comment(0)
G
2

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);
  };
}
Geostatic answered 25/8, 2014 at 8:7 Comment(0)
B
2

Function Overloading via Dynamic Polymorphism in 100 lines of JS

This is from a larger body of code which includes the isFn, isArr, etc. type checking functions. The VanillaJS version below has been reworked to remove all external dependencies, however you will have to define you're own type checking functions for use in the .add() calls.

Note: This is a self-executing function (so we can have a closure/closed scope), hence the assignment to window.overload rather than function overload() {...}.

window.overload = function () {
    "use strict"

    var a_fnOverloads = [],
        _Object_prototype_toString = Object.prototype.toString
    ;

    function isFn(f) {
        return (_Object_prototype_toString.call(f) === '[object Function]');
    } //# isFn

    function isObj(o) {
        return !!(o && o === Object(o));
    } //# isObj

    function isArr(a) {
        return (_Object_prototype_toString.call(a) === '[object Array]');
    } //# isArr

    function mkArr(a) {
        return Array.prototype.slice.call(a);
    } //# mkArr

    function fnCall(fn, vContext, vArguments) {
        //# <ES5 Support for array-like objects
        //#     See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Browser_compatibility
        vArguments = (isArr(vArguments) ? vArguments : mkArr(vArguments));

        if (isFn(fn)) {
            return fn.apply(vContext || this, vArguments);
        }
    } //# fnCall

    //# 
    function registerAlias(fnOverload, fn, sAlias) {
        //# 
        if (sAlias && !fnOverload[sAlias]) {
            fnOverload[sAlias] = fn;
        }
    } //# registerAlias

    //# 
    function overload(vOptions) {
        var oData = (isFn(vOptions) ?
                { default: vOptions } :
                (isObj(vOptions) ?
                    vOptions :
                    {
                        default: function (/*arguments*/) {
                            throw "Overload not found for arguments: [" + mkArr(arguments) + "]";
                        }
                    }
                )
            ),
            fnOverload = function (/*arguments*/) {
                var oEntry, i, j,
                    a = arguments,
                    oArgumentTests = oData[a.length] || []
                ;

                //# Traverse the oArgumentTests for the number of passed a(rguments), defaulting the oEntry at the beginning of each loop
                for (i = 0; i < oArgumentTests.length; i++) {
                    oEntry = oArgumentTests[i];

                    //# Traverse the passed a(rguments), if a .test for the current oArgumentTests fails, reset oEntry and fall from the a(rgument)s loop
                    for (j = 0; j < a.length; j++) {
                        if (!oArgumentTests[i].tests[j](a[j])) {
                            oEntry = undefined;
                            break;
                        }
                    }

                    //# If all of the a(rgument)s passed the .tests we found our oEntry, so break from the oArgumentTests loop
                    if (oEntry) {
                        break;
                    }
                }

                //# If we found our oEntry above, .fn.call its .fn
                if (oEntry) {
                    oEntry.calls++;
                    return fnCall(oEntry.fn, this, a);
                }
                //# Else we were unable to find a matching oArgumentTests oEntry, so .fn.call our .default
                else {
                    return fnCall(oData.default, this, a);
                }
            } //# fnOverload
        ;

        //# 
        fnOverload.add = function (fn, a_vArgumentTests, sAlias) {
            var i,
                bValid = isFn(fn),
                iLen = (isArr(a_vArgumentTests) ? a_vArgumentTests.length : 0)
            ;

            //# 
            if (bValid) {
                //# Traverse the a_vArgumentTests, processinge each to ensure they are functions (or references to )
                for (i = 0; i < iLen; i++) {
                    if (!isFn(a_vArgumentTests[i])) {
                        bValid = _false;
                    }
                }
            }

            //# If the a_vArgumentTests are bValid, set the info into oData under the a_vArgumentTests's iLen
            if (bValid) {
                oData[iLen] = oData[iLen] || [];
                oData[iLen].push({
                    fn: fn,
                    tests: a_vArgumentTests,
                    calls: 0
                });

                //# 
                registerAlias(fnOverload, fn, sAlias);

                return fnOverload;
            }
            //# Else one of the passed arguments was not bValid, so throw the error
            else {
                throw "poly.overload: All tests must be functions or strings referencing `is.*`.";
            }
        }; //# overload*.add

        //# 
        fnOverload.list = function (iArgumentCount) {
            return (arguments.length > 0 ? oData[iArgumentCount] || [] : oData);
        }; //# overload*.list

        //# 
        a_fnOverloads.push(fnOverload);
        registerAlias(fnOverload, oData.default, "default");

        return fnOverload;
    } //# overload

    //# 
    overload.is = function (fnTarget) {
        return (a_fnOverloads.indexOf(fnTarget) > -1);
    } //# overload.is

    return overload;
}();

Usage:

The caller defines their overloaded functions by assigning a variable to the return of overload(). Thanks to chaining, the additional overloads can be defined in series:

var myOverloadedFn = overload(function(){ console.log("default", arguments) })
    .add(function(){ console.log("noArgs", arguments) }, [], "noArgs")
    .add(function(){ console.log("str", arguments) }, [function(s){ return typeof s === 'string' }], "str")
;

The single optional argument to overload() defines the "default" function to call if the signature cannot be identified. The arguments to .add() are:

  1. fn: function defining the overload;
  2. a_vArgumentTests: Array of functions defining the tests to run on the arguments. Each function accepts a single argument and returns truethy based on if the argument is valid;
  3. sAlias (Optional): string defining the alias to directly access the overload function (fn), e.g. myOverloadedFn.noArgs() will call that function directly, avoiding the dynamic polymorphism tests of the arguments.

This implementation actually allows for more than just traditional function overloads as the second a_vArgumentTests argument to .add() in practice defines custom types. So, you could gate arguments not only based on type, but on ranges, values or collections of values!

If you look through the 145 lines of code for overload() you'll see that each signature is categorized by the number of arguments passed to it. This is done so that we're limiting the number of tests we are running. I also keep track of a call count. With some additional code, the arrays of overloaded functions could be re-sorted so that more commonly called functions are tested first, again adding some measure of performance enhancement.

Now, there are some caveats... As Javascript is loosely typed, you will have to be careful with your vArgumentTests as an integer could be validated as a float, etc.

JSCompress.com version (1114 bytes, 744 bytes g-zipped):

window.overload=function(){'use strict';function b(n){return'[object Function]'===m.call(n)}function c(n){return!!(n&&n===Object(n))}function d(n){return'[object Array]'===m.call(n)}function e(n){return Array.prototype.slice.call(n)}function g(n,p,q){if(q=d(q)?q:e(q),b(n))return n.apply(p||this,q)}function h(n,p,q){q&&!n[q]&&(n[q]=p)}function k(n){var p=b(n)?{default:n}:c(n)?n:{default:function(){throw'Overload not found for arguments: ['+e(arguments)+']'}},q=function(){var r,s,t,u=arguments,v=p[u.length]||[];for(s=0;s<v.length;s++){for(r=v[s],t=0;t<u.length;t++)if(!v[s].tests[t](u[t])){r=void 0;break}if(r)break}return r?(r.calls++,g(r.fn,this,u)):g(p.default,this,u)};return q.add=function(r,s,t){var u,v=b(r),w=d(s)?s.length:0;if(v)for(u=0;u<w;u++)b(s[u])||(v=_false);if(v)return p[w]=p[w]||[],p[w].push({fn:r,tests:s,calls:0}),h(q,r,t),q;throw'poly.overload: All tests must be functions or strings referencing `is.*`.'},q.list=function(r){return 0<arguments.length?p[r]||[]:p},l.push(q),h(q,p.default,'default'),q}var l=[],m=Object.prototype.toString;return k.is=function(n){return-1<l.indexOf(n)},k}();
Barrault answered 27/12, 2017 at 19:51 Comment(0)
P
2

there is no actual overloading in JS, anyway we still can simulate method overloading in several ways:

method #1: use object

function test(x,options){
  if("a" in options)doSomething();
  else if("b" in options)doSomethingElse();
}
test("ok",{a:1});
test("ok",{b:"string"});

method #2: use rest (spread) parameters

function test(x,...p){
 if(p[2])console.log("3 params passed"); //or if(typeof p[2]=="string")
else if (p[1])console.log("2 params passed");
else console.log("1 param passed");
}

method #3: use undefined

function test(x, y, z){
 if(typeof(z)=="undefined")doSomething();
}

method #4: type checking

function test(x){
 if(typeof(x)=="string")console.log("a string passed")
 else ...
}
Pruitt answered 1/4, 2019 at 8:5 Comment(0)
A
2

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

Audiometer answered 14/4, 2019 at 2:45 Comment(0)
M
2

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);
Milliner answered 23/6, 2019 at 9:42 Comment(0)
E
2

While Default parameters is not overloading, it might solve some of the issues that developers face in this area. The input is strictly decided by the order, you can not re-order as you wish as in classical overloading:

function transformer(
    firstNumber = 1,
    secondNumber = new Date().getFullYear(),
    transform = function multiply(firstNumber, secondNumber) {
        return firstNumber * secondNumber;
    }
) {
    return transform(firstNumber, secondNumber);
}

console.info(transformer());
console.info(transformer(8));
console.info(transformer(2, 6));
console.info(transformer(undefined, 65));

function add(firstNumber, secondNumber) {
    return firstNumber + secondNumber;
}
console.info(transformer(undefined, undefined, add));
console.info(transformer(3, undefined, add));

Results in (for year 2020):

2020
16160
12
65
2021
2023

More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters

Equivoque answered 16/1, 2020 at 15:36 Comment(0)
L
2

The Typescript Handbook mentions Overloads. While checking types and doing different logic based on results has been mentioned before, this approach defining multiple named functions to work with a typing system might be interesting to readers. Here is how TypeScript achieves creating a function that accepts multiple types of arguments that will direct the function logic to do different things based on incoming arguments and types:

The answer is to supply multiple function types for the same function as a list of overloads. This list is what the compiler will use to resolve function calls. Let’s create a list of overloads that describe what our pickCard accepts and what it returns.

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x: any): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
  }
}

let myDeck = [
  { suit: "diamonds", card: 2 },
  { suit: "spades", card: 10 },
  { suit: "hearts", card: 4 },
];

let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

With this change, the overloads now give us type checked calls to the pickCard function.

In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, it’s customary to order overloads from most specific to least specific.

Note that the function pickCard(x): any piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling pickCard with any other parameter types would cause an error.

Lambdacism answered 4/11, 2020 at 15:38 Comment(0)
A
1

We made over.js to solve this problem is a very elegant way. You can do:

var obj = {

  /**
   * Says something in the console.
   *
   * say(msg) - Says something once.
   * say(msg, times) - Says something many times.
   */
  say: Over(
    function(msg$string){
      console.info(msg$string);
    },
    function(msg$string, times$number){
      for (var i = 0; i < times$number; i++) this.say(msg$string);
    }
  )

};
Adopted answered 7/10, 2013 at 15:58 Comment(0)
T
1

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.

Teriteria answered 20/5, 2014 at 18:38 Comment(0)
S
1

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

Shaylashaylah answered 15/12, 2014 at 9:13 Comment(0)
G
1

JavaScript is untyped language, and I only think that makes sense to overload a method/function with regards to the number of params. Hence, I would recommend to check if the parameter has been defined:

myFunction = function(a, b, c) {
     if (b === undefined && c === undefined ){
          // do x...
     }
     else {
          // do y...
     }
};
Glary answered 25/11, 2016 at 19:39 Comment(1)
Just want to note that untyped does not mean "no types".Jayson
U
1

As of July 2017, the following has been the common technique. Note that we can also perform type checking within the function.

function f(...rest){   // rest is an array
   console.log(rest.length);
   for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3);  // 3 1 2 3
Uniliteral answered 24/7, 2017 at 8:10 Comment(0)
G
1

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.

Grafton answered 1/11, 2017 at 6:40 Comment(0)
A
0

The first option really deserves attention cause it's the thing I've come up in quite complex code setup. So, my answer is

  1. Using different names in the first place

With a little but essential hint, names should look different for computer, but not for you. Name overloaded functions like: func, func1, func2.

Aridatha answered 10/9, 2013 at 8:7 Comment(1)
I was going to try overloading but decided to just use different names, e.g. getDeviceInfoByID and getDeviceInfoByType...Donn
H
0

So I really liked this way of doing things that I found in secrets of the javascript ninja

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

you then use addMethod to add overloaded functions to any object. The main confusion in this code for me was the use of fn.length == arguments.length -- this works because fn.length is the number of expected parameters, while arguments.length is the number of parameters that are actually called with the function. The reason the anonymous function has no argument is because you can pass in any number of arguments in javascript and the language is forgiving.

I liked this because you can use it everywhere - just create this function and simply use the method in whatever code base you want.

It also avoids having a ridiculously large if/switch statement, which becomes hard to read if you start writing complex code (the accepted answer will result in this).

In terms of cons, I guess the code is initially a little obscure...but I'm not sure of others?

Hosea answered 7/2, 2014 at 5:43 Comment(0)
J
0

I like @AntouanK's approach. I often find myself offering a function with different numbers o parameters and different types. Sometimes they don't follow a order. I use to map looking the types of parameters:

findUDPServers: function(socketProperties, success, error) {
    var fqnMap = [];

    fqnMap['undefined'] = fqnMap['function'] = function(success, error) {
        var socketProperties = {name:'HELLO_SERVER'};

        this.searchServers(socketProperties, success, error);
    };

    fqnMap['object'] = function(socketProperties, success, error) {
        var _socketProperties = _.merge({name:'HELLO_SERVER'}, socketProperties || {});

        this.searchServers(_socketProperties, success, error);
    };

    fqnMap[typeof arguments[0]].apply(this, arguments);
}
Jammiejammin answered 28/5, 2015 at 11:56 Comment(0)
H
0

I've been using this function to prettify my overloads for years:

function overload(){
  const fs = arguments, fallback = fs[fs.length - 1];
  return function(){
    const f = fs[arguments.length] || (arguments.length >= fs.length ? fallback : null);
    return f.apply(this, arguments);
  }
}

Demostrated:

function curry1(f){
  return curry2(f, f.length);
}

function curry2(f, minimum){
  return function(...applied){
    if (applied.length >= minimum) {
      return f.apply(this, applied);
    } else {
      return curry2(function(...args){
        return f.apply(this, applied.concat(args));
      }, minimum - applied.length);
    }
  }
}

export const curry = overload(null, curry1, curry2);

Take a look at jQuery's off method:

  function off( types, selector, fn ) {
    var handleObj, type;
    if ( types && types.preventDefault && types.handleObj ) {

        // ( event )  dispatched jQuery.Event
        handleObj = types.handleObj;
        jQuery( types.delegateTarget ).off(
            handleObj.namespace ?
                handleObj.origType + "." + handleObj.namespace :
                handleObj.origType,
            handleObj.selector,
            handleObj.handler
        );
        return this;
    }
    if ( typeof types === "object" ) {

        // ( types-object [, selector] )
        for ( type in types ) {
            this.off( type, selector, types[ type ] );
        }
        return this;
    }
    if ( selector === false || typeof selector === "function" ) {

        // ( types [, fn] )
        fn = selector;
        selector = undefined;
    }
    if ( fn === false ) {
        fn = returnFalse;
    }
    return this.each( function() {
        jQuery.event.remove( this, types, fn, selector );
    } );
  }

Many overloaded functions when optimized for performance are nigh unreadable. You have to decipher the head of the function. This is perhaps faster than using an overload function like I provide; however, it is slower from a human perspective with regard to identifying which overload was called.

Hutchinson answered 29/6, 2018 at 1:21 Comment(0)
L
-1

I am working on a library that provides class like code capabilities to Javascript, currently it supports constructors, inheritance, methods overload by number of params and by types of params, mixins, statics properties and singleton.

See an example of method overloading using that library:

eutsiv.define('My.Class', {
    constructor: function() {
        this.y = 2;
    },
    x: 3,
    sum: function() {
        return this.x + this.y;
    },
    overloads: {
        value: [
            function() { return this.x + ', ' + this.y },
            function(p1) { this.x = p1; },
            function(p1, p2) { this.x = p1; this.y = p2; }  // will set x and y
        ]
    }
});

var test = new My.Class({ x: 5 });   // create the object
test.value();                        // will return '5, 2'
test.sum();                          // will return 7
test.value(13);                      // will set x to 13
test.value();                        // will return '13, 2'
test.sum();                          // will return 15
test.value(10, 20);                  // will set x to 10 and y to 20
test.value();                        // will return '10, 20'
test.sum();                          // will return 30

Any feedback, bug fixes, docs and tests improves are welcome!

https://github.com/eutsiv/eutsiv.js

Library answered 21/11, 2013 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.