ユーザ用ツール

サイト用ツール


javascript:class

差分

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

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
javascript:class [2011/07/05 23:04] – [プロトタイプチェーン] nullponjavascript:class [2016/01/19 07:56] (現在) – [継承] nullpon
行 1: 行 1:
 ====== クラス ====== ====== クラス ======
-厳密にはJavaScriptにクラスはない。機能の異なるオブジェクトは存在するが、それらは持っているプロパティやメソッドが異なっているだけで、オブジェクトの性質には違いはない。 
  
-===== コンストラタ =====+===== クラス構文 =====
  
-Construct関数を不可視プロパティとして持っているオブジェトは、Construct関数で定義されたプロパティを持つインスタンスを生成することができる+ECMAScript 2015からラス構文が導入された。
  
-Construct関数を持っているオブジェ、いくつかのグロバルオブジェクトと、ユーザ定義した関数オブジェクトある。関数を定義ると、定義された関数オブジェクトはコンストラクタとなり、その関数自身がConstruct関数となる。+<code javascript> 
 +'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; 
 +  }  
 +}
  
-  * Boolean +var hoge = new Hoge(1);
-  * Number +
-  * String +
-  * Array +
-  * Object +
-  * Function +
-  * RegExp +
-  * Date+
  
-<code javascript> +hoge.print();   // => 1 と出力 
-var s = new String("a"); + 
-var d new Date();+hoge.value 2; 
 + 
 +console.log(hoge.value  // => 2 と出力
 </code> </code>
  
 +これは以前のprototypeによるクラス定義のシンタックスシュガーにすぎず、Hogeは関数オブジェクトとして定義されている。
 +
 +<code>
 +typeof(Hoge);   // => function
 +</code>
 +
 +ただし関数としての呼び出しには制限がかけられており、newを付けずに呼び出すとエラーになる。
 +
 +<code>
 +Hoge();   // => TypeError: Class constructors cannot be invoked without 'new'
 +</code>
 +
 +==== 継承 ====
 +
 +<code>
 +class Fuga extends Hoge {
 +  // メソッド
 +  print2() {
 +    console.log(this._value * 2);
 +  }
 +}
 +
 +var fuga = new Fuga(3);
 +
 +fuga.print();    // => 3 と出力
 +fuga.print2();   // => 6 と出力
 +</code>
 +
 +
 +==== staticメソッド ====
 +
 +<code>
 +class Piyo extends Hoge{
 +  // メソッド
 +  static piyo() {
 +    console.log('ピヨピヨ');
 +  }
 +}
 +
 +Piyo.piyo();    // => ピヨピヨ と出力
 +</code>
 +
 +
 +===== prototypeによるクラス定義 =====
 +
 +ここからはES5以前の話
 +
 +==== コンストラクタ ====
  
-==== ユーザ定義のオブジェクト型 ====+関数はコンストラタとして働く。コンスラクタとして使う関数は、慣例として大文字で名前を定義する。
  
 <code javascript> <code javascript>
行 48: 行 111:
 </code> </code>
  
-コンストラクタとして使う関数は、慣例として大文字で名前を定義する。+==== constructor プロパティ ====
  
-===== プロトタイプ =====+生成されたインスタンスは constructor というプロパティを持っており、自分のコンスラクにアクセスできる。
  
-全てのオブジェクトは constructor というプロパティを持っている。これは自分を生成したコンストラクタ関数へのリファレンスである。+<code javascript> 
 +function Greet() { 
 +    // ... 
 +}
  
-constructor は prototype というオブジェクトを持っている。あるオブジェクトに対して存在しないメソッドAが呼び出された時、自分のconstructor の prototype がメソッドAを持っていれば、それが実行される。+var greet = new Greet();
  
-よってコンストラクタ関数の prototype に対してメソッドを定義すれば、そのメソッドを生成したインスタンスから呼び出す事ができる。また、prototype はインスタンス間で共有されるので無駄な関数オブジェクトが生成されることもない。(クラス定義1のようにコンストラクタ関数でメソッドを定義すると、コンストラクタを呼ぶたびに関数オブジェクトを作成するので無駄だが、prototype へのメソッド設定ならば一度で良いので無駄が無い)+greet.constructor;   // => Greet 
 +</code>
  
-このため、実際のプロミングで、メソッドは、prototype に定義し、プロパティはコンストラクタで定義するのが一般的である。+==== プロトタイプ ==== 
 + 
 +コンストクタは prototype というプロパティを持っている。
  
 <code javascript> <code javascript>
-// クラス定義2 
 function Greet() { function Greet() {
-    this.message = "hello";+   // ... 
 +
 +Greet.prototype;               // => Greet { }  
 + 
 +var greet = new Greet(); 
 +greet.constructor.prototype;   // => Greet { } 
 +</code> 
 + 
 +new演算子で作成されたインスタンスは、自分のコンストラクタの prototype が持っているプロパティやメソッドに、あたかも自分のメソッドやプロパティであるかのようにアクセスできる。 
 + 
 +よって prototype にプロパティやメソッドを定義してインスタンスで利用することができる。ただし全てのインスタンスで共有されてしまうため、メソッドのみ prototype に定義するのが一般的である。 
 + 
 +<code javascript> 
 +// クラス定義2 
 +function Greet(message) { 
 +  // プロパティ定義 
 +    this.message = message;
 } }
  
 +// メソッド定義
 Greet.prototype.say = function() { Greet.prototype.say = function() {
     return this.message     return this.message
 }    }   
  
-var greet = new Greet();+var greet = new Greet("hello");
  
-greet.say();+greet.say();   // => "hello"
 </code> </code>
  
 +prototypeを丸ごと上書きして置き換えることもできる。
  
-prototypeを丸ごと上書きして置き換えることもできます。 
 <code javascript> <code javascript>
 // クラス定義3 // クラス定義3
-function Greet() { +function Greet(message) { 
-    this.message = "hello";+  // プロパティ定義 
 +    this.message = message;
 } }
  
行 89: 行 175:
 }; };
  
-var greet = new Greet();+var greet = new Greet("world");
  
 greet.say(); greet.say();
 </code> </code>
  
-prototypeを上書きし場合とでな場合では厳密には異なンスタンス作成する。+==== __proto__ プロパティ ==== 
 + 
 +new演算子で作成されインスタンスは内部的に <html>__proto__</html> といプロパティを持っている。これはコンストラク関数の prototype と全くオブジェクト参照してい。 
 + 
 +<code javascript> 
 +var greet = new Greet(); 
 +greet.__proto__ === Greet.prototype;               // => true  
 +greet.__proto__ === greet.constructor.prototype;   // => true 
 +</code> 
 + 
 +これは隠しプロパティ扱いの場合もあるので、実際のプログラミングでは constructor.prototype を使うのがよい
  
 ===== プロトタイプチェーン ===== ===== プロトタイプチェーン =====
  
-オブジェクトがプロパティを持っていなければコンストラクタの prototype からプロパティを探すが、その prototype 該当するプロパティを持っていなければ、さらにその prototype のコンスラクの prototype からロパティ探す。こ仕組みをプロトタイプチェーンと呼ぶ+インスタンスは、<html>__proto__</html>(以下プロタイプと呼ぶ)持っているメソッドやプロパティを、自分メソッドやプロパティであるかのように呼び出ことできる。 
 + 
 +あるインスタンスに対してメソッドAを呼び出したとき、もし、インスタンスがメソッドAを持っておらず、プロトタイプがメソッドAを持っていれば、プロトタイプのメソッドAが呼び出され。もしプロトタイプもメソッドAを持っていなければ、プロトタプのプロトタイプがメソッドAを持っているか探す
  
-プロトタイプチェーンを使うと継承のような事ができるが、実際に使われる事は少ない+この仕組みをプロトタイプチェーンと呼ぶ。プロトタイプチェーンを使うと継承に似たことができる。
  
 <code javascript> <code javascript>
行 124: 行 222:
 var jpNightGreet = new JpNightGreet(); var jpNightGreet = new JpNightGreet();
  
-// Greet型のメソッドsayが呼び出される+// Greet型の(プロトタイプのプロトタイプ)メソッドsayが呼び出される
 jpNightGreet.say(); jpNightGreet.say();
 </code> </code>
  
 +プロトタイプチェーンを最後までさかのぼると、最終的にはObjectになる。よってObjectのメソッドは全てのインスタンスから呼び出すことができる。(といってもvalueOfとtoString、toSourceぐらいしか無い)
javascript/class.1309907064.txt.gz · 最終更新: 2011/07/05 23:04 by nullpon