LoginSignup
1
4

More than 5 years have passed since last update.

JavaScript Math.roundをオーバーロードして小数点以下X桁を指定して四捨五入する

Last updated at Posted at 2017-05-31

元記事

小数点以下X桁を指定して四捨五入 - Qiita

こちらの記事で、Math.roundを拡張したいという感じだったので、

オーバーロードできるのかな?

と思って、書いてみました。

最初はこう書いた

  Math.round_original = Math.round_original || Math.round;
  Math.round = function (number, pricision) {
    var _pow;
    switch (arguments.length) {
    case 1:
      return Math.round_original(number);
    case 2:
      _pow = Math.pow(10, pricision);
      return Math.round_original(number * _pow) / _pow;
    }
  }

Math.round_original = Math.round_original || Math.round;
ここでは、round_original が定義されていれば、そのまま使い、定義されていなければ、Math.roundをバックアップする、的な処理を書いています。
名前空間でよく使うやつです。

で、Math.roundをバックアップした上で、新しくMath.rooundを定義してarguments引数で処理を分岐しました。

クロージャーを使いました。

round_original という関数を外部でバッファとして持たせる、というのは、グローバル汚染にもなりそうなので、ちょっとださいな。と思い、クロージャーの実装が使えないかな、と思って調べました。

JSなんてもう怖くない!JavaScript/ES2015速習ガイド - Qiita
こことかに書かれているのがクロージャーのシンプルな例です。

クロージャー、というあまり使われない単語を見ると「わからんわー」という気持ちになるかもしれません。私はなりました。

が、書いてみると簡単ですよ。

function の中から、return function するやり方です。
シンプルなクロージャーの例を応用して、クロージャーを生成する関数自体の実行を代入とともに無名関数の即時実行でやっています。こういう日本語表現が正しいのかどうかはわからないですが、実装はそう難しくないです。

  Math.round = function (round_original) {
    return function (number, pricision) {
      var _pow;
      switch (arguments.length) {
      case 1:
        return round_original(number);
      case 2:
        _pow = Math.pow(10, pricision);
        return round_original(number * _pow) / _pow;
      }
    }
  }(Math.round);

これで、Math.roundのオーバーロードができました。

動作確認コード

全文を載せておきます。
テストフレームワーク的な check関数 で、動作確認しています。こちらの記事ご参考ください。

JavaScriptで(そしてどんな言語でも同じで)世界一簡単なテストフレームワークを作って使おう - Qiita

check関数を見れば、Math.roundが正常動作していることがわかります。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title></title>
<script>

  var check = function (a, b, message) {
    if (a === b) {
      return true;
    }
    if (typeof message == 'undefined') {
      message = '';
    } else {
      message = 'Test:' + message + '\n';
    }
    message = message +
        'A != B' + '\n' +
        'A = ' + a + '\n' +
        'B = ' + b;
    alert(message);
    return false;
  };

var main1 = function () {

  Math.round_original = Math.round_original || Math.round;
  Math.round = function (number, pricision) {
    var _pow;
    switch (arguments.length) {
    case 1:
      return Math.round_original(number);
    case 2:
      _pow = Math.pow(10, pricision);
      return Math.round_original(number * _pow) / _pow;
    }
  }

  check(5,    Math.round(5));
  check(5,    Math.round(5.4));
  check(6,    Math.round(5.5));
  check(5.4,  Math.round(5.44, 1));
  check(5.5,  Math.round(5.45, 1));
  check(5.5,  Math.round(5.54, 1));
  check(5.6,  Math.round(5.55, 1));

  check(5.04,  Math.round(5.044, 2));
  check(5.05,  Math.round(5.045, 2));
  check(5.05,  Math.round(5.054, 2));
  check(5.06,  Math.round(5.055, 2));

  alert('test finish ');
};

var main2 = function () {

  Math.round = function (round_original) {
    return function (number, pricision) {
      var _pow;
      switch (arguments.length) {
      case 1:
        return round_original(number);
      case 2:
        _pow = Math.pow(10, pricision);
        return round_original(number * _pow) / _pow;
      }
    }
  }(Math.round);

  check(5,    Math.round(5));
  check(5,    Math.round(5.4));
  check(6,    Math.round(5.5));
  check(5.4,  Math.round(5.44, 1));
  check(5.5,  Math.round(5.45, 1));
  check(5.5,  Math.round(5.54, 1));
  check(5.6,  Math.round(5.55, 1));

  check(5.04,  Math.round(5.044, 2));
  check(5.05,  Math.round(5.045, 2));
  check(5.05,  Math.round(5.054, 2));
  check(5.06,  Math.round(5.055, 2));

  alert('test finish ');
};

//main1();
main2();

</script>

  </head>
<body>


</body>
</html>

1
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4