1.はじめに
JSで使いやすいクラスの雛形があればいいなと思ったので試行錯誤してみます。
ES6まではクラスという概念はサポートされないので、あくまでクラスっぽく書くというのがポイントになります。
フレームワーク頼らず、フルスクラッチでクラスを作る時にJAVAや.NETみたいにキレイに分かりやすく書きましょう。
2.要件
- PrivateとPublicの変数、メソッドをそれぞれ管理できる
- 複数インスタンスをnewで作成可能にする
- イベントハンドラを利用してデータ更新を検知して何かできるようにする
3.やってみよう!
// window.mylibという名前空間的なものを作って初期化
window.mylib = Object.create({});
// window.mylib以下にクラス的なものを作ります。
window.mylib.UserModule = function(svname) {
// 自身のクラスをselfとして保持
var _self = this;
// プライベート変数
var _country = "Japan";
// パブリック変数
_self.time = new Date();
_self.service_name = svname;
// プライベートメソッド
var formatName = function(number){
return _self.service_name + "へようこそ(" + _country + ")" + number;
};
// パブリックメソッド
_self.getFormattedName = function(){
return formatName(1);
};
_self.setCountry = function(country){
_country = country;
};
_self.getCountry = function(){
return _country;
};
// イベントハンドラの登録
_self.model = {"user_id": 1 , "name": "JIRO" , "address": "Ebisu", "service_name": undefined};
_self.proxy = new Proxy(_self.model, {
get: function(object, target, newval) {
console.log('get handler is called');
console.log(target);
console.log(object);
console.log(newval);
},
set: function(object, target, newval){
console.log('set handler is called');
console.log(object);
console.log(target);
console.log(newval);
object[target] = newval;
if(target == "service_name"){
_self.service_name = newval;
}
console.log(_self.model);
}
});
return _self;
};
1.window.mylibという名前空間的なものを作って初期化
window.mylib = Object.create({});
2.window.mylib以下にクラス的なものを作る
window.mylib.UserModule = function(svname) {
3.JSではthisの値がスコープによって変化してしまうので_selfにthisを予め入れておく
var _self = this;
4.パブリック変数とメソッド
_self.service_name = svname;
_self.getFormattedName = function(){
5.プライベート変数とメソッド
var _country = "Japan";
var formatName = function(number){
6.イベントハンドラ
Proxyを使ってイベントハンドラを設定
_self.proxy = new Proxy(_self.model, {...});
4.実行結果を確認してみる
インスタンス1作成
var um1 = new window.mylib.UserModule("楽天");
um1.getFormattedName();
>"楽天へようこそ(Japan)1"
インスタンス2作成
var um2 = new window.mylib.UserModule("アマゾン");
um2.getFormattedName();
>"アマゾンへようこそ(Japan)1"
private変数の値が変わるか確認
um1.setCountry("England");
um2.setCountry("Israel");
um1.getCountry();
>"England"
um2.getCountry();
>"Israel"
public変数の値が変わるか確認
um1.service_name = "メルカリ";
um2.service_name = "ヤフー";
um1.getFormattedName();
>"メルカリへようこそ(England)1"
um2.getFormattedName();
>"ヤフーへようこそ(Israel)1"
プロキシ経由でのアクセスをしてイベントハンドラが正常に動くか確認
um1.proxy.service_name = "通販さいと";
>set handler is called
>Object {user_id: 1, name: "JIRO", address: "Ebisu", service_name: undefined}
>service_name
>通販さいと
>Object {user_id: 1, name: "JIRO", address: "Ebisu", service_name: "通販さいと"}
um1.getFormattedName();
>"通販さいとへようこそ(England)1"