2

Please: only pure vanilla JS code. No jQuery or other external things, thank you. :)

How can I create a function that contains sub-functions but also returns a value if no sub-function is called?

For example, let's take a number variable num.

I want to add a round() function to the number variable; if it's called directly, I want it to round up or down depending on the variable's actual value.

var num=4.12;
num.prototype.round=function(){return Math.round(this);}

Now I wand round() to have sub-functions that will round up or down, disregarding the decimal values.

num.prototype.round.up=function(){return Math.ceil(this);}
num.prototype.round.down=function(){return Math.floor(this);}

If I do that and log num.round() to console, it does what it's supposed to. But if I log num.round.up() to console, I get an error telling me that num.round.up() is not a function.

So I try putting the sub-functions into the main function declaration like this:

num.prototype.round=function(){
    var n=this;
    this.up=function(){return Math.ceil(n);}
    this.prototype.round.down=function(){return Math.floor(n);}
    return Math.round(n);
}

Then again, num.round() will return the correctly rounded value, but both num.round.up() and num.round.down() will return "not a function" errors.

I'm going nuts trying to figure this out... I didn't only try what I mentioned above, but I also tried doing this with immediately executing functions like this:

num.round=(function(){
    return function(){
        var that=this;
        /* anything in here is already useless because this
        is no longer num's value but [Object window]... */
    }
})();

I guess part of the trouble is that I'm so weak at OOP that I just have no clue about the correct terminology... naturally, that doesn't help when searching for clues or when it comes to knowing any potential reasons why something like this should not work...

So is there any way at all to do this?

Rob
  • 81
  • 1
  • 9
  • You cannot define round as a function and at the same place as an object holding two functions (`up` and `down`). – ssc-hrep3 Feb 25 '16 at 19:06
  • Only constructors have a `prototype` property by default. `4.12` is not an object, even less a constructor. – Oriol Feb 25 '16 at 19:06
  • 2
    Basically, the problem is that when you call `num.round.up`, the `this` value will be the `num.round` function, not `num`. Then I don't recommend this approach. Better allow `num.round` to receive an optional parameter, and call it like `num.round()`, `num.round('up')` or `num.round('down')`. – Oriol Feb 25 '16 at 19:09
  • 1
    "*So is there any way at all to do this?*" - yes, but not a good or OOP one. – Bergi Feb 25 '16 at 19:16
  • @Bergi could you point me in the right direction please? I have no intentions of making this function or whatever it is inheritable or so on. It should just serve that one purpose in one place. – Rob Feb 25 '16 at 19:43
  • @Rob: Have a look at https://stackoverflow.com/questions/15884096/organize-prototype-javascript-while-perserving-object-reference-and-inheritance and https://stackoverflow.com/questions/16502467/prototype-deep-scope-of-this-to-access-instances-scope – Bergi Feb 25 '16 at 19:47

2 Answers2

1

Well you can pass a parameter to the function. Not the exact implementation you want, just an alternative:

var num = function (defaultNumValue) {
  var delegation = {
    'up': 'ceil',
    'down': 'floor'
  };
  return {
    round: function (val) {
      return Math[ delegation[val] || 'round' ](defaultNumValue); 
    }
  }
};

var sth = num(1.5);
sth.round(); // 2
sth.round('up'); // 2
sth.round('down'); // 1
Pravin
  • 1,671
  • 5
  • 23
  • 36
0

May be something like:

function num(n) {
    this.num=n;
    this.round=Math.round(n);
    this.up=Math.ceil(n);
    this.down=Math.floor(n);
    this.up2=function(){return Math.ceil(n);}
}
var num = new num(4.12);
alert(num.num);
alert(num.round);
alert(num.up);
alert(num.down);
alert(num.up2());
Viv
  • 326
  • 1
  • 6
  • Maybe I should've pointed out explicitly that I would want to have the .up/.down functions "after" the .round one. Just for that reason, your suggestion would not work for me. Also, doesn't what you do just calculate everything once when num is set and then return static values? I'm definitely not looking for that, sorry. – Rob Feb 25 '16 at 20:57