ユーザ用ツール

サイト用ツール


javascript:class

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

次のリビジョン
前のリビジョン
javascript:class [2010/02/08 05:43] – 外部編集 127.0.0.1javascript:class [2016/01/19 07:56] (現在) – [継承] nullpon
行 1: 行 1:
 ====== クラス ====== ====== クラス ======
-JavaScriptにはクラスはないが、関数オブジェクトをコンストラクタとして呼び出すことができる。 
  
-===== Functionオブジェト ===== +===== クラス構文 ===== 
-関数を定義すると、新しい Function オブジェ作成されます+ 
 +ECMAScript 2015からラス構文導入され 
 <code javascript> <code javascript>
-function ClassA(){+'use strict';   // クラス構文の使用にはstrictモードが必須です 
 + 
 +class Hoge { 
 +  // コンストラクタ 
 +  constructor(val) { 
 +    this._value = val   
 +  } 
 +  
 +  // メソッド 
 +  print() { 
 +    console.log(this._value); 
 +  } 
 +   
 +  // ゲッター 
 +  get value() { 
 +    return this._value; 
 +  } 
 +   
 +  // セッター 
 +  set value(val) { 
 +    this._value = val; 
 +  } 
 } }
-window.alert(ClassA instanceof Function);  // true+ 
 +var hoge = new Hoge(1); 
 + 
 +hoge.print();   // => 1 と出力 
 + 
 +hoge.value = 2; 
 + 
 +console.log(hoge.value)   // => 2 と出力
 </code> </code>
  
-===== クラス定義とイ作成 ===== +これは以前のprototypeによるクラス定義のシンタックシュガーにすぎず、Hogeは関数オブジェクトとして定義されている 
-Functionオブジェクト演算子 new を使うと新しいインスタンスを作成できま。Function オブジェクトはコンストラクタとして働きます。 + 
-<code javascript+<code> 
-function MyClass(){ +typeof(Hoge);   // => function
-+
-var my = new MyClass(); +
-window.alert(my instanceof MyClass);       // true +
-window.alert(my.constructor == MyClass);   // true+
 </code> </code>
-インスタンス my の constructor プロパティは 関数オブジェクト MyClass となり、my は MyClass のインスタンスとみなされます。 
  
-===== メソッド定義 ===== +ただし関数としての呼び出しに制限がかけられており、new付けずに呼び出すとエラーに 
-コンストラクタは prototype プロパティを持っており、 prototype に関数オブジェクトセットることで、インスタンスのメソッドとなります。 + 
-<code javascript+<code> 
-function MyClass(){+Hoge();   // => TypeError: Class constructors cannot be invoked without 'new' 
 +</code> 
 + 
 +==== 継承 ==== 
 + 
 +<code> 
 +class Fuga extends Hoge { 
 +  // メソッド 
 +  print2() { 
 +    console.log(this._value * 2); 
 +  }
 } }
-MyClass.prototype.execute = function () { 
-    window.alert("hoge"); 
-}; 
-var my = new MyClass(); 
-my.execute();     // hogeと表示 
  
-var my2 = new MyClass(); +var fuga = new Fuga(3); 
-my2.execute();    // hoge表示+ 
 +fuga.print();    // => 3 と出力 
 +fuga.print2();   // => 6 出力
 </code> </code>
  
-インスタンスに直接メソッドを付加することもできます + 
-<code javascript+==== staticメソッド ==== 
-// インスタンス自身にメソッドを定義 + 
-my.execute2 = function () { +<code> 
-   window.alert("fuga");  +class Piyo extends Hoge{ 
-}; +  // メソッド 
-my.execute2();     // fugaと表示 +  static piyo() { 
-my2.execute2();    // my2はメソッドexecute2を持たないのでエラー+    console.log('ピヨピヨ'); 
 +  } 
 +
 + 
 +Piyo.piyo();    // => ピヨピヨ と出力
 </code> </code>
  
-==== プロトタイプチェイン ==== + 
-メソッドを呼び出すと、まずインスタンス自身が呼び出されたメソッドを持っていないかチェックし、持っいればそれ実行します。+===== prototypeによるクラス定義 ===== 
 + 
 +ここからはES5以前の話 
 + 
 +==== コンスラクタ ==== 
 + 
 +関数はコンストラクとして働く。コンストラタとて使う関数は慣例とし大文字で名前定義 
 <code javascript> <code javascript>
-function Hoge() {+// クラス定義1 
 +// コンストラクタ関数 
 +function Greet() { 
 +    // プロパティの定義 
 +    this.message =  "hello"; 
 + 
 +    // メソッドの定義 
 +    this.say = function() { 
 +        return this.message; 
 +    };
 } }
-var hoge = new Hoge(); 
-hoge.execute = function() { alert("あ") }; 
  
-hoge.execute();  // "あ"と表示される+// インスタンスの生成 
 +var greet = new Greet(); 
 + 
 +// メソッドの呼び出し 
 +greet.say(); 
 </code> </code>
-インスタンス自身がメソッドっていない場合は、コンストラクタのprototypeからメソッドを探して呼び出します+ 
 +==== constructor プロパティ ==== 
 + 
 +生成されたインスタンスは constructor というプロパティっており自分のコンストラクタにアクセスできる 
 <code javascript> <code javascript>
-function Fuga() {+function Greet() { 
 +    // ...
 } }
-Fuga.prototype = hoge; 
  
-var fuga = new Fuga(); +var greet = new Greet(); 
-fuga.execute() // プロトタイプ(hoge)のexecuteメソッドが呼ばれ、"あ"と表示される。+ 
 +greet.constructor  // => Greet
 </code> </code>
  
-コンストラクタprototypeもメソッドを持っていない場合は、prototypeオブジェクトのコンストラクタのprototypeを探して呼び出します+==== プロトタイプ ==== 
 + 
 +コンストラクタは prototype というプロパティを持ってい 
 <code javascript> <code javascript>
-function Piyo() {+function Greet() { 
 +   // ...
 } }
-Piyo.prototype = new Fuga();+Greet.prototype;               // => Greet { } 
  
-var piyo = new Piyo(); +var greet = new Greet(); 
-piyo.execute() // プロトタイプ(Fugaのインスタンス)のプロトタイプ(hoge)の execute メソッドが呼ばれ、"あ"と表示される。+greet.constructor.prototype  // => Greet { }
 </code> </code>
  
-ようにプロトタイプをさかってメソッドを探す仕組みをプロトタイプチェインと呼びます+new演算子で作成されたインスタンスは、自分コンスラクタの prototype が持っているプロパティやメソッドに、あたかも自分のメソッドやプロパティであるかのようにアクセスできる
  
 +よって prototype にプロパティやメソッドを定義してインスタンスで利用することができる。ただし全てのインスタンスで共有されてしまうため、メソッドのみ prototype に定義するのが一般的である。
  
-===== プロパティの定義 ===== 
-代入式を実行した時点でプロパティが生成されるのでプロパティを宣言をする必要はありません。 
 <code javascript> <code javascript>
-function MyClass(){ +// クラス定義2 
-    this.hoge = "ホゲ";     // プロパティhogeが生成+function Greet(message) { 
 +  // プロパティ定義 
 +    this.message = message;
 } }
-MyClass.prototype.printHoge = function () { + 
-    print(this.hoge);     +// メソッド定義 
-} +Greet.prototype.say = function() { 
-MyClass.prototype.printFuga = function () { +    return this.message 
-    print(this.fuga);     +   
-+ 
-MyClass.prototype.setMohe = function (mohe) { +var greet = new Greet("hello"); 
-    this.mohe = mohe;                 + 
-} +greet.say();   // ="hello"
-var my = new MyClass(); +
-my.printHoge(); +
-my.fuga = "ふが"+
-my.printFuga(); +
-my.setMohe("モゲ"); +
-print(my.mohe);+
 </code> </code>
-メソッドやプロパティは全て外部から自由にアクセス可能。内部表現の隠蔽は難しい(できなくはない…) 
  
-===== クラス定義 ===== +prototypeを丸ごと上書きしてき換えこともで 
-最近では prototype にメソッド一つずつセットしていくよりも、prototypeプロパティそのものを書き換えてしまうことが多い。このとinitializeというメソッドを定義して、コンストラクタで呼び出す作法が一般的+
 <code javascript> <code javascript>
-function MyClass(arg){ +// クラス定義3 
-    this.initialize(arg);+function Greet(message) { 
 +  // プロパティ定義 
 +    this.message = message;
 } }
-MyClass.prototype = { + 
-    initialize: funtion(arg) { +Greet.prototype = { 
-       this.hoge = arg; +    say: function() { 
-    } +        return this.message 
-    printHoge: function() { +    }   
-        print(this.hoge); +
-    }, +
-    printFuga: function () { +
-        print(this.fuga);     +
-    }, +
-    setMohe: function (mohe) { +
-        this.mohe = mohe;                 +
-    }+
 }; };
-var my = new MyClass("ほげ"); + 
-my.printHoge(); +var greet = new Greet("world"); 
-my.fuga = "ふが"; + 
-my.printFuga(); +greet.say();
-my.setMohe("モゲ"); +
-window.alert(my.mohe);+
 </code> </code>
  
-===== 無名関数からクラスを生成 ===== +==== __proto__ プロパティ ==== 
-無名関数もコンストラクタになる。+ 
 +new演算子で作成されたインスタンスは、内部的に <html>__proto__</html> というプロパティを持っている。これはコンストラクタ関数の prototype と全くオブジェクトを参照している。 
 <code javascript> <code javascript>
-var MyClass = function(arg) { +var greet new Greet(); 
-    this.initialize(arg)   +greet.__proto__ === Greet.prototype;               // => true  
 +greet.__proto__ === greet.constructor.prototype;   // => true 
 +</code> 
 + 
 +これは隠しプロパティ扱いの場合もあるので、実際のプログラミングでは constructor.prototype を使うのがよい。 
 + 
 +===== プロトタイプチェーン ===== 
 + 
 +インスタンスは、<html>__proto__</html>(以下プロトタイプと呼ぶ)が持っているメソッドやプロパティを、自分のメソッドやプロパティであるかのように呼び出すことができる。 
 + 
 +あるインスタンスに対してメソッドAを呼び出したとき、もし、インスタンスがメソッドAを持っておらず、プロトタイプがメソッドAを持っていれば、プロトタイプのメソッドAが呼び出される。もしプロトタイプもメソッドAを持っていなければ、プロトタイプのプロトタイプがメソッドAを持っているか探す。 
 + 
 +この仕組みをプロトタイプチェーンと呼ぶ。プロトタイプチェーンを使うと継承に似たことができる。 
 + 
 +<code javascript> 
 +function Greet() { 
 +    this.message = "hello";
 } }
-MyClass.prototype = +Greet.prototype.say = function() { 
-    initialize: function(arg) { +    return this.message
-        this.hoge = arg; +
-    }, +
-    inspect: function() { +
-        print(this.prototype); +
-        print(this.constructor); +
-        for (var i in this) { +
-            print (i + "=" + this[i]); +
-        } +
-    }+
 } }
  
-var my = new MyClass(1000); +function NightGreet() { 
-my.fuga = "fugafuga"; +    this.message = "good night"; 
-my.inspect();+
 +NightGreet.prototype = new Greet();  // Greetを継承 
 + 
 +function JpNightGreet() { 
 +    this.message = "おやすみなさい"; 
 +
 +NightGreet.prototype = new NightGreet();  // NightGreetを継承 
 + 
 + 
 +// JpNightGreet型のインスタンス生成 
 +var jpNightGreet = new JpNightGreet(); 
 + 
 +// Greet型の(プロトタイプのプロトタイプ)メソッドsayが呼び出される 
 +jpNightGreet.say();
 </code> </code>
  
 +プロトタイプチェーンを最後までさかのぼると、最終的にはObjectになる。よってObjectのメソッドは全てのインスタンスから呼び出すことができる。(といってもvalueOfとtoString、toSourceぐらいしか無い)
javascript/class.1265607815.txt.gz · 最終更新: 2011/07/05 17:01 (外部編集)