元記事
こちらの記事で、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>