0

I have this method called 'leer' (Learn in English) that atm takes in 2 words. 1 for a category and 1 to put in that category. Now I would like to add functionality whereby I can add a bunch of words to one category.

WoordenSchat.prototype.leer = function(categorie,naam){
    if (!this.hasOwnProperty(categorie)){
        this[categorie] = []
        this[categorie].push(naam)
    }
    else {
        this[categorie].push(naam)
    }
}

I could solve this by figuring out what sort of variable I receive in 'naam' via typeOf and then act accordingly, but I feel like this would result in a messy piece of code.

What I would like to do is have 2 functions:

  • leer (categorie,naam)
  • leer (categorie, [naam])

where by the one with an array of names (naam (Dutch) in plural) would call the first one in a for loop.

Is this possible in JavaScript? Because as far as I know there is no way of telling a Javascript method: "You take in this type of variable and this type only"

I know in python you could do things like this def functionName (categorie:str, naam: str) etc.

MrKickkiller
  • 501
  • 10
  • 22
  • You can create many sub functions like `_leerWithArray`, `_leerWithString`, but at last, you still need handle the types of naam and pass the aruguments to each subfunction. – fuyushimoya Aug 18 '15 at 14:05
  • 2
    You could loop via [`arguments.length`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments) and call `leer('x', a, b, c, d)` with as many strings as you like. – Alex K. Aug 18 '15 at 14:05
  • There is no built-in function overloading in JS. One way or another, you'll *have* to examine the arguments – haim770 Aug 18 '15 at 14:07
  • @fuyushimoya: Problem is : For the assignment it has to be seamless. In your advice I would have to dedicate 'leer ' to splitting the two types apart and then having subfunctions do the work. Kinda not what I wanna do, but if I have to, i'll do it :/ – MrKickkiller Aug 18 '15 at 14:08
  • No, [there is no method overloading in JS](http://stackoverflow.com/a/12694605/1048572). `typeof` is the way to go here. But if you want to avoid messy code, go with two different methods anyway. – Bergi Aug 18 '15 at 14:10

2 Answers2

2

JavaScript doesn't support function overloading based on parameter types.
However, as @AlexK suggested, you can modify the function to accept a variable amount of parameters:

WoordenSchat.prototype.leer = function(categorie){
    if (!this.hasOwnProperty(categorie)){   // We only need to do this check once.
        this[categorie] = [];
    } 
    for(var i = 1; i < arguments.length; i++){
        this[categorie].push(arguments[i]); // `arguments[i]` is the current `naam`.
    }
};

This starts looking for parameters at arguments[1], since arguments[0] is categorie. Then, every single naam passed to leer will be pushed onto the array.

You can call the function like this:

myWoordenSchat.leer('programmeren', 'functies', 'variabelen', 'constanten');

You can add as many or as few parameters after categorie as you wish.

This function can be simplified a little bit more:

WoordenSchat.prototype.leer = function(categorie){
    this[categorie] = this[categorie] || []; // Make sure `this[categorie]` exists
    for(var i = 1; i < arguments.length; i++){
        this[categorie].push(arguments[i]);  // `arguments[i]` is the current `naam`.
    }
};

Now, you could modify the function to accept stings or an array, instead:

WoordenSchat.prototype.leer = function(categorie, namen){
    this[categorie] = this[categorie] || [];

    if(typeof namen === 'string'){   // The first parameter after `categorie` is a string
        namen = arguments.splice(1); // So, get all parameters after `categorie` as array
    }

    for(var i = 0; i < namen.length; i++){
        this[categorie].push(namen[i]);
    }
};

So, if the first parameter after categorie is a string, iterate over all parameters, otherwise, iterate over the namen array.

You should be able to call the function like this:

myWoordenSchat.leer('programmeren', 'functies');
myWoordenSchat.leer('programmeren', 'functies', 'variabelen', 'constanten');
myWoordenSchat.leer('programmeren', ['functies', 'variabelen', 'constanten']);
Community
  • 1
  • 1
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • Not what the assignment calls for, but I like the answer anyway. It also displays something that I didn't know yet: That it doesn't matter what amount of arguments you input in the function name, that can still hold many arguments. – MrKickkiller Aug 18 '15 at 14:17
  • What _exactly_ does the assignment tell you to do, then? Any way, I'm happy to be of help. – Cerbrus Aug 18 '15 at 14:18
  • This is the functionality we have to recreate with this WoordenSchat and Madlibs: https://gyazo.com/c574a51527aac502e2838e07cc18f819 – MrKickkiller Aug 18 '15 at 14:20
  • That `madlib.leren('naam', ('Mercator', 'Caesar'))` and the one two below that, with the `{}` aren't even valid JavaScript syntax. Those are impossible to recreate. I'll see about adding something to support the array, though. – Cerbrus Aug 18 '15 at 14:22
  • @MrKickkiller: I added another option to my answer, so now it accepts arrays, too. – Cerbrus Aug 18 '15 at 14:40
  • @Cerbrus: the OP didn't like typeof.. however, your first solution is good enough! – Mario Trucco Aug 18 '15 at 14:43
  • @MarioTrucco: the OP didn't like the suggestion to write separate sub-functions, from what I read. – Cerbrus Aug 18 '15 at 14:44
  • @Cerbrus: s/he wrote "I could solve this by figuring out what sort of variable I receive in 'naam' via typeOf and then act accordingly, but I feel like this would result in a messy piece of code." – Mario Trucco Aug 18 '15 at 14:46
  • @MarioTrucco: Ah yes, I see. I hope my solution using `typeof` is less messy than the OP thought it would be :-) – Cerbrus Aug 18 '15 at 14:49
0

If ES2015 is an option:

WoordenSchat.prototype.leer = function(categorie, ...namen) {
  if (! this.hasOwnProperty(categorie)) {
    this[categorie] = [];
  }
  this[categorie].push(...namen);
}
robertklep
  • 198,204
  • 35
  • 394
  • 381