TL;TD;
JavaScriptのデフォルトのDateオブジェクトは月が0$\sim$11で使いにくいのでES2015から導入されたclassの継承を使ってハックする。
JavaScriptによるclassの継承
classの継承を使うことで、prototypeを拡張することなくデフォルトのDateオブジェクトをハックする。
module.exports=class extends Date{
constructor(...args){
if( args.length<2 ) super(...args);
else{
const year=args.shift();
const month=args.shift()-1;
super( year, month, ...args);
}
}
getYear(){ return super.getFullYear(); }
setMonth(month){ super.setMonth(month-1); }
getMonth(month){ return super.getMonth()+1; }
}
Nodeでmodule.exports
で名前をつけずexportした。ブラウザ用ならexports default
である。
月をセットするセッターとコンストラクタは1を引いてデフォルトを呼ぶ。
特にコンストラクターはrest parametersを用いて文字列、エポック秒を用いたコンストラクタはデフォルトのコンストラクタにそのまま渡し。月が関わるものだけ、配列のshiftを使って月まで取り出して残りはデフォルトのコンストラクタに渡している。
ゲッターは1を足して返すようにしている。
getYearは非推奨であり2018=>118というややこしい値を返すので内部でgetFullYear
を返すようにした(同じくsetYearもハックするべきかもしれない)。
検証用コード
ここでは同じ名前のDateがブロックスコープを変えることで共存できることも検証したが安全性としては問題が残るので実際に使う場合はより安全な名付けとルール作りが必要である。
{
console.log('===== modified Date Object Test START =====');
const Date=require('modDate');
const date=new Date();
console.log(date);
console.log(date.getYear());
const monthArr=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
for( const month of monthArr ){
console.log("Month =", month);
date.setMonth(month);
console.log(date);
console.log("date.getMonth()=", date.getMonth());
const date2=new Date(1000, month, 10);
console.log(date2);
}
console.log('===== modified Date Object Test FINISH =====');
}
console.log('===== default Date Object Test START =====');
const date=new Date();
console.log(date);
console.log(date.getYear());
const monthArr=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
for( const month of monthArr ){
console.log("Month =", month);
date.setMonth(month);
console.log(date);
console.log("date.getMonth()=", date.getMonth());
}
console.log('===== default Date Object Test FINISH =====');
modDateファイルをDateで受けることによりあたかもDateのように使うことができる。また、constなので影響範囲はブロックスコープに限られるので外ではデフォルトのDateとして使える。
まとめ
classのextends(継承)を使うことで影響範囲を限った形で既存のインスタンスをハックできる。
rest parametersを用いることで様々な値を受けられるコンストラクター(関数)にも簡単に対応できる。
影響範囲が限られているのでガンガン書き換えても問題は大きくならないので例えばgetDayあたりを日、月、火、....
とかにするのもアリだろうし。toStringをより読みやすい形に変えるなどもできそうである。
コメントを受けて
getDay
はgetDayJa
もしくはgetDayStringJa
にするべきだと思う。あえてgetYoubi
とかでもいいかも
toString
はあえて名前つけルールを標準からずらしてstring
もしくはforLog
とかがありだと思います。