オブジェクト指向JavaScript
最近、あんまりアウトプットできてない...
反省...
オブジェクト指向JavaScriptについて勉強したのでメモです。
ほぼ↓に書いてあることをまとめただけの備忘録的なものです。
用語
⁃ ネームスペース
開発者があらゆる機能をアプリケーション固有の一意な名前にまとめることができる容器
⁃ 継承
あるクラスが別のクラスから特性を引き継ぐことを指します
⁃ カプセル化
データとそのデータを使用するメソッドをまとめる手法
⁃ 抽象化
実世界のモデルが、オブジェクトの複雑な継承、メソッド、プロパティの集合体によって適切に再現されている状態を指す
⁃ ポリモーフィズム
別々のクラスが同じメソッドやプロパティを定義可能で有ること
プロトタイプベースプログラミング
クラスを使わずにプロトタイプオブジェクトをデコレート(あるいは拡張)してそのオブジェクトの持つ挙動を再利用することで実現されるOOPモデル
JavaScriptのオブジェクト指向プログラミング
ネームスペース
ネームスペースはメソッド、プロパティ、オブジェクトを包含する別のオブジェクト
※ JavaScriptでは通常のオブジェクトとネームスペースとの間に、言語レベルの違いがない。
ネームスペースを作成するときは、グローバルオブジェクトを一つ作成して、すべての変数、メソッド、関数をそのオブジェクトのプロパティとすれば良い。
MYAPPが定義済みであれば、それを使用。なければ、空のオブジェクトを作成
var MYAPP = MYAPP || {};
サブネームスペースの作成
MYAPP.event = {};
変数、関数、メソッドを追加
// 共通のメソッドやプロパティ向けに MYAPP.commonMethod という名前のコンテナを作成 MYAPP.commonMethod = { regExForName: "", // 名前を検証するための正規表現を定義 regExForPhone: "", // 電話番号を検証するための正規表現を定義 validateName: function(name){ // 名前に対してなんらかの処理を行う。"this.regExForName" を使用して // 変数 regExForName にアクセス可能 }, validatePhoneNo: function(phoneNo){ // 電話番号に対してなんらかの処理を行う } } // オブジェクトとともにメソッドを定義する MYAPP.event = { addListener: function(el, type, fn) { // 処理 }, removeListener: function(el, type, fn) { // 処理 }, getEvent: function(e) { // 処理 } // 他のメソッドやプロパティを追加できる } // addListener メソッドを使用する構文: MYAPP.event.addListener("yourel", "type", callback);
クラス
JavaScriptはクラスのコンストラクタとして関数を使用する。 Personクラスの作成
ver Person = function() {};
オブジェクト(クラスのインスタンス) Objオブジェクトの新たなインスタンスを生成するには new obj文を使用する。 Personコンストラクタから2つのインスタンスの生成
var person1 = new Person(); var person2 = new Person();
プロパティ(オブジェクトの属性)
プロパティは、クラス内にある変数。オブジェクトのインスタンスは全て、それらのプロパティを持つ。
プロパティはコンストラクタ内で設定される
Var Person = funtion (firstname) { This.firstName - firstName; } Person.prototype.sayHello = fuction() { console.log(“Hello, I’m ” + this.firstName); }; var person1 = new Person(’bob’); person1.sayHello(); var Person = function (firstName) { this.firstName = firstName; }; Person.prototype.sayHello = function() { console.log("Hello, I'm " + this.firstName); }; var person1 = new Person("Alice"); var person2 = new Person("Bob"); var helloFunction = person1.sayHello; // "Hello, I'm Alice" と出力 person1.sayHello(); // "Hello, I'm Bob" と出力 person2.sayHello(); // "Hello, I'm undefined" と出力 // (strict モードでは TypeError で失敗する) helloFunction(); // true と出力 console.log(helloFunction === person1.sayHello); // true と出力 console.log(helloFunction === Person.prototype.sayHello); // "Hello, I'm Alice" と出力 helloFunction.call(person1);
sayHello関数を参照しているもの(person1, Person.prototype, helloFunctionなど)すべてが、同一の関数を示している。 thisの値は関数の呼び出し方に依存する。もっとも一般的な、オブジェクトのプロパティから関数にアクセスする形式(person1.sayHello())でthisをよびだすときは、その関数を持つオブジェクト(person1)をthisに設定する helloFunctionからthisを呼び出すと、グローバルオブジェクトをthisに設定する。
Function.callまたはFunction.applyを使用してThisを明示的に設定もできる。
継承
1つ以上のクラスを特化したバージョンとしてクラスを作成する方法。JavaScriptでは単一継承のみサポートしている。
var Person = function(firstName) { this.firstName = firstName; }; Person.prototype.walk = function() { console.log(‘I am walking’); } Person.prototype.sayHello = function() { console.log(‘Hello, I’m’ + this.firstName); } // Studentコンストラクタの定義 Function Student(firstName, subject) { // 親のコンストラクタを呼び出す。呼び出しの際にThisが設定されるようにする Person.call(this.firstname); this.subject = subject; }; // Person.prototypeを継承する、 Student.prototypeオブジェクトを作成 // Student.prototypeを生成するためにnew Personを使ってはならない Student.prototype = Object.create(Person.prototype); // constructorプロパティがStudentを指すように設定する Student.prototype.constructor = Student; Student.prototype.sayHello = function() { // … } Student.prototype.sayGoodBye = function() { // … } var student1 = new Student(‘janet’, ‘Math’); student1.sayHello(); student1.walk(); student1.sayGoodBYe(); console.log(student1 instanceof Person); // true console.log(student1 instanceof Student); // true Function createObjcet(proto) { Function ctor() {} ctor.prototype = proto; Return new ctor(); }
オブジェクトをインスタンス化する方法を問わずに、thisの参照先を適切に指定するのはときに難しい。 これを用意にするシンプルなイディオム。
var Person = function(firstName) { If (this instanceof Person) { this.firstName = firstName; } else { Return new Person(fistName); } }
抽象化
抽象化は、取り組んでいる問題の箇所を継承や合成によってモデル化することを可能にする仕組みです...?よくわからん
var foo = function () {}; // "foo is a Function: true" と出力 console.log('foo is a Function: ' + (foo instanceof Function)); // "foo.prototype is an Object: true" と出力 console.log('foo.prototype is an Object: ' + (foo.prototype instanceof Object));
ポリモーフィズム
すべてのメソッドやプロパティがprototypeプロパティの内部で実装されているのと同じように、異なるクラスで同じ名前のメソッドを定義できる。