atwiki-logo
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このウィキの更新情報RSS
    • このウィキ新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡(不具合、障害など)
ページ検索 メニュー
とりあえず雑記帳(跡地)
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
とりあえず雑記帳(跡地)
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
とりあえず雑記帳(跡地)
ページ検索 メニュー
  • 新規作成
  • 編集する
  • 登録/ログイン
  • 管理メニュー
管理メニュー
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • このウィキの全ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ一覧(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このwikiの更新情報RSS
    • このwikiの新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡する(不具合、障害など)
  • atwiki
  • とりあえず雑記帳(跡地)
  • JavaScript
  • JavaScriptでクラスもどき

とりあえず雑記帳(跡地)

JavaScriptでクラスもどき

最終更新:2011年11月15日 23:01

fujiyan

- view
管理者のみ編集可
WebコミックLibraryhttp://web-comi.appspot.com/
GAE/JとSlim3で作成してみた、各出版社から配信されているWebコミックをまとめて閲覧できるサイトです。只今、実験運用中…

Functionオブジェクトあれこれの内容を総動員して、クラスっぽいことが実現できます。

クラスもどき

  • 下記のようなJavaベースの擬似コードで表現されたクラスを仮定します。
class Foo {
    var propertyA;
 
    Foo(str) {
        this.propertyA = str;
    }
 
    void methodA(mark) {
        alert(mark + this.propertyA + mark);
    }
}
 
  • クラス名はFooです。
  • プロパティpropertyAを持ちます。
  • コンストラクタを持ち、引数として文字列を受け取り、propertyAに設定します。
  • methodAを持ち、引数として文字列を受け取り、propertyAの内容をその文字列で囲んで表示します。

  • 上記のクラスを、JavaScriptでそれっぽく実現すると下記のようなコードになります。
var Foo = function(str) {
    this.propertyA = str;
}
 
Foo.prototype.methodA = function(mark) {
    alert(mark + this.propertyA + mark);
}
 

// 以下、使用例
var obj1 = new Foo("obj1");
obj1.methodA("***");
 
var obj2 = new Foo("obj2");
obj2.propertyA = obj2.propertyA + "@@@";
obj2.methodA("+++");
 

小分けにして説明

var Foo = function(str) {
    this.propertyA = str;
}
 
  • クラス名を名前にした変数Fooを定義し、コンストラクタとなるFunctionオブジェクトを設定します。
    • これにより、new Foo()という記述で、オブジェクトの生成が可能になります。
  • コンストラクタの内部で、プロパティとなるpropertyAを、new演算子で生成した際のコンテキストオブジェクトに定義します。
    • これにより、new Foo()で生成したオブジェクトには、全てpropertyAが定義されることになります。
  • コンストラクタは、引数strを受け取り、生成したオブジェクトのpropertyAに設定します。

Foo.prototype.methodA = function(mark) {
    alert(mark + this.propertyA + mark);
}
 
  • コンストラクタとなるFunctionオブジェクトFooのprototypeに対して、メソッド名を名前にしたプロパティmethodAを定義し、メソッドとなるFunctionオブジェクトを設定します。
    • これにより、new Foo()で生成したオブジェクトに対して、obj1.methodA()という表記で、メソッドとなるFunctionオブジェクトが実行できます。
    • obj1.methodA()と呼び出した際は、methodA内のthisは、obj1を指します。


クラス継承もどき

  • さらに、継承っぽいこともやらせてみましょう
  • やっぱり、下記のようなJavaベースの擬似コードで表現されたクラスを仮定します。
// クラスFooの定義は、上記と同じ
 
class ExtendedFoo extends Foo {
    var propertyB;
 
    ExtendedFoo(strA, strB) {
        super(strA)
        this.propertyB = strB;
    }
 
    void methodA(mark) {
        alert(mark + this.propertyA + this.propertyB + mark);
    }
 
    void methodB(mark) {
        alert(mark + this.propertyB + mark);
    }
}
 
  • クラス名はExtendedFooです。
  • クラスFooを継承しています。
  • Fooで定義されたプロパティの他、独自のプロパティpropertyBを持ちます。
  • コンストラクタを持ち、引数として文字列を2つ受け取ります。
    • 最初にスーパークラスFooのコンストラクタを呼び出します。引数にstrAを指定します。
    • strBは、propertyBに設定します。
  • Fooで定義されたmethodAをオーバーライドします。引数として文字列を受け取り、propertyAとpropertyBの内容を連結し、その文字列で囲んで表示します。
  • 独自のメソッドmethodBを持ちます。

  • 上記のクラスを、やっぱりJavaScriptでそれっぽく実現すると下記のようなコードになります。
var ExtendedFoo = function(strA, strB) {
    Foo.apply(this, [strA]);
    this.propertyB = strB;
}
 
ExtendedFoo.prototype = new Foo();
 
ExtendedFoo.prototype.methodA = function(mark) {
    alert(mark + this.propertyA + this.propertyB + mark);
}
 
ExtendedFoo.prototype.methodB = function(mark) {
    alert(mark + this.propertyB + mark);
}
 

//以下、使用例
var obj1 = new ExtendedFoo("obj1", "abc");
obj1.methodA("***");
obj1.methodB("***");
 
var obj2 = new ExtendedFoo("obj2", "xyz");
obj2.propertyA = obj2.propertyA + "@@@";
obj2.methodA("+++");
obj2.methodB("+++");
 

やっぱり小分けにして説明

var ExtendedFoo = function(strA, strB) {
    Foo.apply(this, [strA]);
    this.propertyB = strB;
}
 
  • クラス名を名前にした変数ExtendedFooを定義し、コンストラクタとなるFunctionオブジェクトを設定します。
    • これにより、new ExtendedFoo()という記述で、オブジェクトの生成が可能になります。
  • コンストラクタの内部で、FunctionオブジェクトFooのapply()メソッドを呼んでいます。
    • apply()メソッドを適用するコンテキストオブジェクトとして、this(new演算子で生成した際のコンテキストオブジェクト)を指定しています。
      • apply()メソッドの第2引数には、Foo本来の引数を配列で指定しています。値として、strAを渡しています。
      • これにより、new ExtendedFoo()で生成したオブジェクトに対して、Fooの初期処理が適用されることになります(プロパティ継承とsuper()のエミュレート)。
  • その後、ExtendedFooの独自プロパティとなるpropertyBを、new演算子で生成した際のコンテキストオブジェクトに定義します。
    • これにより、new ExtendedFoo()で生成したオブジェクトには、全てpropertyBが定義されることになります。
  • コンストラクタは、引数strBを生成したオブジェクトのpropertyAに設定します。

ExtendedFoo.prototype = new Foo();
 
  • ExtendedFooのプロパティprototypeに対して、Fooをコンストラクタとしたオブジェクトを設定しています。
    • これにより、Fooのメソッドとなるプロパティを、ExtendedFooをコンストラクタとしたオブジェクトからも参照できるようになります(メソッド継承のエミュレート)。

ここは詳しく説明

  • クラス継承もどきを実現するには、new ExtendedFoo()で作成したオブジェクトのプロトタイプチェーンに、
    • ExtendedFooのメソッドに当たるFunctionオブジェクト
    • Fooのメソッドに当たるFunctionオブジェクト
  • を組み込むようにします。

  • ExtendedFooのメソッドについては、ExtendedFoo.prototypeに、メソッドに当たるFunctionオブジェクトのプロパティを定義します。
    • これによって、作成されたオブジェクトの__proto__にExtendedFoo.prototypeが設定されるので、プロトタイプチェーンに組み込まれます。
  • では、Fooのメソッドに当たるFunctionオブジェクトをプロトタイプチェーンに組み込むには?
    • ExtendedFooの親クラスがFooという継承階層に倣って、__proto__にはExtendedFooのメソッドを、プロトタイプチェーンの親に当たる__proto__.__proto__に、Fooのメソッドが設定されるようにすれば目的は達成されます。
    • new Foo()で作成したオブジェクトの__proto__にFoo.prototypeが設定されるので、そのオブジェクトがnew ExtendedFoo()で作成したオブジェクトの__proto__に設定されればいいですね(Foo.prototypeにFooのメソッドが定義されているので)。
    • ということで、ExtendedFoo.prototypeにnew Foo()で作成したオブジェクトを設定しているのです。
    • ExtendedFooのメソッドは、new Foo()で作成したオブジェクトのプロパティとして設定していきます。
  • なお、Fooのメソッドを呼ぶ際には、new Foo()で作成したオブジェクトに設定されたFunctionオブジェクトが用いられますが、コンテキストオブジェクトはnew Foo()で作成したオブジェクトではなく、メソッド起動時に指定したオブジェクト(new ExtendedFoo()で作成したオブジェクト)です。
  • あと、new Foo()でコンストラクタ引数を渡していませんが、これは渡す必要が無いからです。new Foo()で生成したオブジェクトで利用したいのはFunctionオブジェクトだけであり、それ以外のプロパティは利用しないためです。

ExtendedFoo.prototype.methodA = function(mark) {
    alert(mark + this.propertyA + this.propertyB + mark);
}
 
ExtendedFoo.prototype.methodB = function(mark) {
    alert(mark + this.propertyB + mark);
}
 
  • コンストラクタとなるFunctionオブジェクトExtendedFooのprototype(new Foo()で生成したオブジェクト)に対して、メソッド名を名前にしたプロパティmethodAを定義し、メソッドとなるFunctionオブジェクトを設定します。
    • これにより、new Foo()で生成したオブジェクトに対して、obj1.methodA()という表記で、メソッドとなるFunctionオブジェクトが実行できます。
    • methodAは、Foo.prototypeでも定義されていますが、プロトタイプチェーンの検索順序により、ExtendedFoo.prototypeで定義したほうが実行対象となります(メソッドのオーバーライドのエミュレート)。
    • obj1.methodA()と呼び出した際は、methodA内のthisは、obj1を指します。
  • また、ExtendedFooの独自メソッドとして、メソッド名を名前にしたプロパティmethodBを定義し、メソッドとなるFunctionオブジェクトを設定します。
    • これにより、new Foo()で生成したオブジェクトに対して、obj1.methodB()という表記で、メソッドとなるFunctionオブジェクトが実行できます。
    • obj1.methodB()と呼び出した際は、methodA内のthisは、obj1を指します。
「JavaScriptでクラスもどき」をウィキ内検索
LINE
シェア
Tweet
とりあえず雑記帳(跡地)
記事メニュー

メニュー

  • トップページ
  • コメント
  • とりあえずインターフェース入門
  • Yesod
  • Haskell
  • Slim3
  • JavaScript
  • Google App Engine
  • Android
  • Facebook
  • GWT
  • OpenSocial
  • Struts 2
  • Subversion
  • Apache
  • JSONIC
  • Flex

  • WebコミックLibraryについて

公式サイト

  • Yesod
  • Haskell
  • Slim3
  • JavaScript - MDN
  • App Engine for Java
  • Android Developers
  • Google Web Toolkit
  • Struts
  • OpenSocial
  • OSDE

  • ToDo

ここを編集
記事メニュー2
間違いの御指摘は
コメントまでm(_ _)m

更新履歴

取得中です。


ここを編集

総数: -
本日: -
昨日: -
人気記事ランキング
  1. Slim3/とりあえずSlim3アプリケーションを作ろう/Controllerで画面作成
  2. Struts 2
もっと見る
最近更新されたページ
  • 4400日前

    Haskell
  • 4400日前

    Yesod
  • 4400日前

    トップページ
  • 4509日前

    メニュー
  • 4511日前

    Struts 2
  • 4536日前

    コメント
  • 4705日前

    Google App Engine
  • 4743日前

    Slim3/環境構築とプロジェクト作成
  • 4767日前

    Google App Engine/キャッシュの計画
  • 4777日前

    Slim3/文字列の部分一致検索とページング
もっと見る
人気記事ランキング
  1. Slim3/とりあえずSlim3アプリケーションを作ろう/Controllerで画面作成
  2. Struts 2
もっと見る
最近更新されたページ
  • 4400日前

    Haskell
  • 4400日前

    Yesod
  • 4400日前

    トップページ
  • 4509日前

    メニュー
  • 4511日前

    Struts 2
  • 4536日前

    コメント
  • 4705日前

    Google App Engine
  • 4743日前

    Slim3/環境構築とプロジェクト作成
  • 4767日前

    Google App Engine/キャッシュの計画
  • 4777日前

    Slim3/文字列の部分一致検索とページング
もっと見る
ウィキ募集バナー
新規Wikiランキング

最近作成されたWikiのアクセスランキングです。見るだけでなく加筆してみよう!

  1. 鹿乃つの氏 周辺注意喚起@ウィキ
  2. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  3. MadTown GTA (Beta) まとめウィキ
  4. R.E.P.O. 日本語解説Wiki
  5. AviUtl2のWiki
  6. シュガードール情報まとめウィキ
  7. ソードランページ @ 非公式wiki
  8. ドラゴンボール Sparking! ZERO 攻略Wiki
  9. シミュグラ2Wiki(Simulation Of Grand2)GTARP
  10. 星飼いの詩@ ウィキ
もっと見る
人気Wikiランキング

atwikiでよく見られているWikiのランキングです。新しい情報を発見してみよう!

  1. アニヲタWiki(仮)
  2. ストグラ まとめ @ウィキ
  3. ゲームカタログ@Wiki ~名作からクソゲーまで~
  4. 初音ミク Wiki
  5. 機動戦士ガンダム バトルオペレーション2攻略Wiki 3rd Season
  6. 検索してはいけない言葉 @ ウィキ
  7. オレカバトル アプリ版 @ ウィキ
  8. 発車メロディーwiki
  9. Grand Theft Auto V(グランドセフトオート5)GTA5 & GTAオンライン 情報・攻略wiki
  10. 英傑大戦wiki
もっと見る
全体ページランキング

最近アクセスの多かったページランキングです。話題のページを見に行こう!

  1. 過去の行動&発言まとめ - 鹿乃つの氏 周辺注意喚起@ウィキ
  2. マイティーストライクフリーダムガンダム - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  3. 魚拓まとめ - 鹿乃つの氏 周辺注意喚起@ウィキ
  4. 参加者一覧 - ストグラ まとめ @ウィキ
  5. 1103環境(遊戯王) - アニヲタWiki(仮)
  6. 前作からの変更点 - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  7. 魔獣トゲイラ - バトルロイヤルR+α ファンフィクション(二次創作など)総合wiki
  8. コレクター・ユイ - アニヲタWiki(仮)
  9. サーヴァント/一覧/クラス別 - Fate/Grand Order @wiki 【FGO】
  10. 画像倉庫 - 鹿乃つの氏 周辺注意喚起@ウィキ
もっと見る

  • このWikiのTOPへ
  • 全ページ一覧
  • アットウィキTOP
  • 利用規約
  • プライバシーポリシー

2019 AtWiki, Inc.