Edited at

JavaScriptオブジェクト指向(クラス的なものを作るサンプル)

More than 1 year has passed since last update.


概要

JavaScriptでオブジェクト指向するときのサンプルコードです。

以下のWebサイトを参考にしました。

JavaScript におけるクラスの作成と継承


サンプルコード

(function() {
// For compatibility
// IE10以下に対応
// prototypeとconstructorを設定して継承する
Function.prototype.inherit = function(base) {
var f = function() {};
f.prototype = base.prototype;
this.prototype = new f();
this.prototype.constructor = this;
return this;
};

// 名前空間の文字列を「.」で区切る
function splitNs(nsStr) {
return nsStr.split(".");
}

// 名前空間を作成して末端のオブジェクトを返す
function ret(nsStr) {
function ret_helper(rt, symo) {
if(symo.length > 0) {
var now = symo.shift();
if(!(Object.prototype.toString.call(rt[now])
=== '[object Object]')) {
rt[now] = {};
}
return ret_helper(rt[now], symo);
} else {
return rt;
}
}

return ret_helper(window, splitNs(nsStr));
}

// 指定した名前空間のオブジェクトを指定したオブジェクトから参照できるようにする
window.use = function(nsStr, self) {
var nss = splitNs(nsStr);
var obj = self[nss[0]];
for(var i = 1; i < nss.length; i += 1) {
obj = obj[nss[i]];
}
self[nss[nss.length - 1]] = obj;
};

// 名前空間を作成して受け取った関数のthisに登録されたものをすべて作成した名前空間に登録する
window.ns = function(sym, fn) {
fn.call(ret(sym));
};
})();

(function () {
// 名前空間「rtns.classes」を使用
ns('rtns.classes', function() {
// コンストラクタFooを定義
function Foo() {
this.x = 2;
}

// プロトタイプにメソッドを定義
Foo.prototype.foo = function() {
console.log("foo", this.x);
};

// スタティックメソッドに相当するものを定義
Foo.staticFoo = function() {
console.log("static foo");
};

// 名前空間に登録して外部から参照できるようにする
this.Foo = Foo;
});
})();

(function () {
// rtns.classes.FooをFooとしてアクセスできるようにする
use('rtns.classes.Foo', this);

ns('rtns.classes', function() {
// Fooを親としてコンストラクタBarを定義
function Bar() {
// Fooで定義されているプロパティを作成する
Foo.call(this);

// Bar独自のプロパティ
this.y = 3;
}

// プロトタイプを設定して継承する
// Object.setPrototypeOfが定義されているブラウザではinheritsは不要です
if(Object.setPrototypeOf) {
Object.setPrototypeOf(Bar.prototype, Foo.prototype);
} else {
Bar.inherit(Foo);
}

// Bar独自のメソッドを定義
Bar.prototype.bar = function() {
console.log("bar", this.x, this.y);
};

this.Bar = Bar;
});
})();

(function() {
use('rtns.classes.Foo', this);
use('rtns.classes.Bar', this);

// Fooのインスタンスを作成
var f = new Foo();
// Fooのインスタンスメソッドfooを呼んでみる
f.foo();

// Barのインスタンスを作成
var b = new Bar();
// Fooで定義されているメソッドをプロトタイプチェーンをたどって呼んでみる
b.foo();
// Barで定義されているメソッドを呼んでみる
b.bar();

// FooとBarそれぞれのプロトタイプになにが定義されているか確認
console.log((Foo.prototype.foo)? "Foo has foo" : "Foo has'nt foo");
console.log((Foo.prototype.bar)? "Foo has bar" : "Foo has'nt bar");
console.log((Bar.prototype.foo)? "Bar has foo" : "Bar has'nt foo");
console.log((Bar.prototype.bar)? "Bar has bar" : "Bar has'nt bar");

// Fooのスタティックメソッドを呼んでみる
Foo.staticFoo();
})();