SSJSでも使える!Javascriptで オブジェクト指向プログラミング入門

Slides:



Advertisements
Similar presentations
アルゴリズムとプログラミン グ (Algorithms and Programming) 第6回:クラスとインスタンス クラスの宣言 アクセス修飾子 インスタンスの生成 (new キーワード) this キーワード フィールドとメソッドの実際の定義と使い 方 クラスの宣言 アクセス修飾子 インスタンスの生成.
Advertisements

1 C++ における OOP を用いた 書き方講座 H 山崎貴英. 2 今回の内容 OOP とは? C++ の超基礎 注釈 書いてあるコードはすべて一部抜粋。 コピペだと動かないよ!
オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
1 情報基礎 A 第 9 週 プログラミング入門 VBA の基本文法 1 準備・変数・データの入出力 徳山 豪・全 眞嬉 東北大学情報科学研究科 システム情報科学専攻 情報システム評価学分野.
C++ 基礎. 目次 C++ とは? C++ におけるオブジェクト指向 課題 C++ とは? Cには足りなかったものが付与されて出来た物 具体的には、 情報の隠蔽(カプセル化) 共通の名前付け(関数のオーバーロード) 再利用の仕組み クラスの導入 など オブジェクト指向 C++ では大規模なプログラミングの.
ソフトウェア工学 知能情報学部 新田直也. オブジェクト指向パラダイムと は  オブジェクト指向言語の発展に伴って形成され てきたソフトウェア開発上の概念.オブジェク ト指向分析,オブジェクト指向設計など,プロ グラミング以外の工程でも用いられる.  ソフトウェアを処理や関数ではなくオブジェク.
Scala + Liftフレームワーク その2.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
東京工科大学 コンピュータサイエンス学部 亀田弘之
1.1 C/C++言語 Hello.ccを作りコンパイルしてa.outを作り出し実行する
~手続き指向からオブジェクト指向へ(Ⅰ)~
2008/03/01 D-BOF k.inaba はじめての initial D 2008/03/01 D-BOF k.inaba
Javaのための暗黙的に型定義される構造体
プログラミングパラダイム さまざまな計算のモデルにもとづく、 プログラミングの方法論 手続き型 関数型 オブジェクト指向 代数 幾何.
Step-by-Step Guide on How to Start ALICE Analysis
アルゴリズムとデータ構造1 2007年6月12日
VBA(Visual Basic Application)を使ったプログラミングの初歩概説
JavaServlet&JSP入門 01K0018 中村太一.
プログラミング演習II 2004年10月19日(第1回) 理学部数学科・木村巌.
アルゴリズムとプログラミング (Algorithms and Programming)
Androidソースコード公開後のJNI
Day3 Day4 Day3 Day4.
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
2004年度 サマースクール in 稚内 JavaによるWebアプリケーション入門
オブジェクト指向 プログラミング 第十四回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
第4回JavaScriptゼミ セクション2-8 発表者 直江 宗紀.
JAVA入門後期⑩ 情報処理試験例題解説.
アルゴリズムとプログラミング (Algorithms and Programming)
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
暗黙的に型付けされる構造体の Java言語への導入
Windows PowerShell Cmdlet
第11週:super/subクラス、継承性、メソッド再定義
Nakano School of Business 経営情報ビジネス科 【 Java概論(Test5)】
オブジェクト指向 プログラミング 第十四回 知能情報学部 新田直也.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
Null ヤバイのでなんとかする takeshik.
Null ヤバイのでなんとかする takeshik.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十ニ回 知能情報学部 新田直也.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
アルゴリズムとプログラミング (Algorithms and Programming)
オブジェクト指向プログラミング クラス 継承
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第六回 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
Webページに動きを持たせるJavascript言語について 例題のプログラムを通して体験的に理解することとします。
サブゼミ第7回 実装編① オブジェクト型とキャスト.
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
モグラたたき.
JAVA入門⑥ クラスとインスタンス.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
演算子のオーバーロード.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
例題のプログラムを通して JavaScriptの仕組みを理解することとします。
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第十回 知能情報学部 新田直也.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
プログラミング 2 静的変数.
Presentation transcript:

SSJSでも使える!Javascriptで オブジェクト指向プログラミング入門 KTrick 合同会社 代表 田付 和慶 www.ktrick.com

自己紹介 田付 和慶 (たつき かずのり) ケートリック合同会社 代表 米国で7年間、IBM Connect (旧Lotusphere) の オンラインソリューションを XPages で開発してきました。 会社のスローガン 「若い力を集結させた IBM 技術者集団をめざす!」 (特にICS)

XPagesでの開発を難しく感じる 原因って何でしょう?

1つはやっぱりJavascript? しかも クライアントサイド? サーバーサイド? いきなり2つも覚えろとか・・・(T_T)

最近ではネットでJavascriptのサンプル 漁ってみると、 こんなんだったり、 var myButton = new Button({ label: "Show me!", onClick: function(){ myDialog.set("content", “Hello!"); myDialog.show(); } }, "progbutton").startup(); こんなんだったり、 var func1 = function(){ alert("hello!"); }

なんで function が後ろに来ちゃうの? Javascriptっていえば、 function func1(param){ alert(param); } こうじゃないの? なんで function が後ろに来ちゃうの?

おいおい ちょっと、、、カッコ 多くないか? 他にも、こういったの見たことありませんか? ( function () {      //関数の中身・・・ }() ); おいおい ちょっと、、、カッコ 多くないか? これ、最後のカッコ本当にいるの???

お作法だからしかたないんだ… で諦めていませんか?

Javascriptの構造を少し紐解いて 言語への理解を深くしてもらえたらと思っています。 このセッションでは そういった Javascriptの構造を少し紐解いて 言語への理解を深くしてもらえたらと思っています。

そもそも、オブジェクト指向プログラミング(OOP)をすると なんのメリットがあるのでしょうか?

主なメリットとして ・プログラムの可読性が高まる ・プログラムの再利用がしやすい ・拡張や仕様変更に強くなる 結果、 OOPの概念や仕組みについて触れだすとこのセッションをフルに使っても時間が足らないので割愛しますが、 主なメリットとして ・プログラムの可読性が高まる ・プログラムの再利用がしやすい ・拡張や仕様変更に強くなる 結果、 テストにかかる時間を減らせ、デスマーチの確率を減らせる。 あと、オブジェクト指向が分かっているとなんだかカッコいい、という風潮がある などなど

オブジェクト指向 この言葉から なにを思い浮かべますか?

クラス C# Java C++ UML 移譲 オブジェクト指向プログラミング ポリモーフィズム オーバーロード 継承 オーバーライド インスタンス UML 移譲 クラス オーバーライド C# Java オブジェクト指向プログラミング ポリモーフィズム オーバーロード 派生クラス 抽象クラス C++ 継承

を真っ先に思いうかべた人もいると思います。 オブジェクト指向プログラミングの経験者なら 「クラス」 を真っ先に思いうかべた人もいると思います。

では、 Javascriptにもクラスってあるの?

ないです。 諸説あり

クラスがなくてどうやって オブジェクト指向プログラミング(OOP)するの?

その答えは…

プロトタイプチェイン

そもそも、Javascriptにあるのは オブジェクト のみ

オブジェクトがあればいいのです!(強気) オブジェクト指向なんだから、 オブジェクトがあればいいのです!(強気) クラスなんて飾りです! クラスベースの言語にはそれがわからんのです! (錯乱)

子Class (型) Object (実体) Object (実体) Object (実体) そもそも、クラスってこんなの クラスでオブジェクトの「型」をあ らかじめ定義しておき、そのクラス をもとに実体を生成して利用する。 こうすることで、クラスがもつ機能 (関数)や属性(変数)を持った実 体が量産出来る。 NEW NEW NEW Object (実体) Object (実体) Object (実体)

クラスを持たない Javascriptでは…

プロトタイプチェイン Object (実体) Object (実体) Object (実体) Object (実体) Object (実体) こんなイメージ プロトタイプチェイン Object (実体) オブジェクト(実体)を数珠つな ぎのように繋げて、 オブジェクト自身が知らない関数 や変数への呼び出しがあれば、繋 がりのある別のオブジェクトに移 譲(Delegate)することで見つか るまで遡っていくイメージ。 Dele gate Dele gate Dele gate Object (実体) Object (実体) Dele gate Object (実体) Object (実体)

プロトタイプベースオブジェクト指向言語 このように、 Javascriptではクラスではなくプロトタイプチェインという機構を使い オブジェクト指向プログラミングを実装しているので、 プロトタイプベースオブジェクト指向言語 なんて呼ばれています。

ここからは実際のコードで説明をしていきます。 それでは、 ここからは実際のコードで説明をしていきます。 ※基本的にクライアントサイドJavascriptとして考えて下さい。 サーバーサイドJavascriptではalert() 等できないためですが、基本の考え方は同じです。

まずは基本。

Objectの作り方 var obj = { }; 空っぽのオブジェクトが出来ました。

var obj = { key: value }; Objectの構造 var obj = { name : “Apple”, (例) var obj = { name : “Apple”, size : 500 }; alert(obj.name); プロパティ(キーと値の組み合わせ) 単純ですがこれだけです。

var func = function( ){}; Javascriptでは関数も「値」(第一級オブジェクト) var func = function( ){}; だから変数に代入できます。 そして変数から変数へコピー などの操作もできます。 (例)オブジェクトのプロパティにも代入できます。 var obj = { func1 : function( ) {alert(“hoge”); } }; obj.func1(); // Output “hoge”

いよいよ プロトタイプチェインの説明です。 どんどんいきましょう。 いよいよ プロトタイプチェインの説明です。 JavascriptのOOPの真骨頂

➲ __proto__ ➲prototype Javascriptのプロトタイプチェインを学ぼうとするとき しばしば以下の2つのキーワードが登場します。 ➲ __proto__ ➲prototype この2つの意味の違いをしっかりと理解することが Javascript OOPを理解する上でとても重要になります

➲ __proto__

内部プロパティ[[Prototype]]を持つ ・Javascriptでは全てのオブジェクトは 内部プロパティ[[Prototype]]を持つ という仕様があります。 とは言いつつ、実際には__proto__というプロパティでプログラム から扱える実装が多い。(ChromeやFirefox) 内部プロパティと言っているので、本来 は外から参照出来ない性質のもの

Object (実体) Object (実体) Object (実体) Object (実体) こんなイメージ __proto__ Dele gate Dele gate Dele gate Object (実体) __proto__ Object (実体) __proto__ Object (実体) __proto__

コードで確認 (__proto__が使えるchrome,firefoxで動きます) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); 空っぽなのに 「It is Apple」 が出力されます

コードを順番に確認(1) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); オブジェクトを生成。 name, callMe のプロパティを持つ objApple オブジェクトを生成。 nameプロパティに”Apple”を持つ objBlackbox オブジェクトを生成。 プロパティはなにも持たない。 「It is Apple」 が出力されます

objApple.__proto__に objを代入 コードを順番に確認(2) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); オブジェクトを生成。 name, callMe のプロパティを持つ objApple オブジェクトを生成。 nameプロパティに”Apple”を持つ objApple.__proto__に objを代入 objBlackbox オブジェクトを生成。 プロパティはなにも持たない。

コードを順番に確認(2) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); オブジェクトを生成。 name, callMe のプロパティを持つ objApple オブジェクトを生成。 nameプロパティに”Apple”を持つ objApple.__proto__に objを代入 objBlackbox オブジェクトを生成。 プロパティはなにも持たない。 objBlackbox.__proto__に objAppleを代入

コードで確認(メソッドの確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe();

(1) objBlackboxにはcallMe() メソッドがない コードで確認(メソッドの確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (1) objBlackboxにはcallMe() メソッドがない

(1) objBlackboxにはcallMe() メソッドがない コードで確認(メソッドの確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (2)__proto__にあるオブジェクトを検索 (objApple) (1) objBlackboxにはcallMe() メソッドがない

コードで確認(メソッドの確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (3) objAppleにもcallMe() メソッドがない (2)__proto__にあるオブジェクトを検索 (objApple) (1) objBlackboxにはcallMe() メソッドがない

コードで確認(メソッドの確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (3) objAppleにもcallMe() メソッドがない (4)__proto__にあるオブジェクトを検索 (obj) (2)__proto__にあるオブジェクトを検索 (objApple) (1) objBlackboxにはcallMe() メソッドがない

コードで確認(メソッドの確認) var obj = { name : “none”, (5) objにcallMe() メソッドを発見! var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (3) objAppleにもcallMe() メソッドがない (4)__proto__にあるオブジェクトを検索 (obj) (2)__proto__にあるオブジェクトを検索 (objApple) (1) objBlackboxにはcallMe() メソッドがない

(1) callMe() メソッドが呼ばれます コードで確認(属性の確認) var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (1) callMe() メソッドが呼ばれます

(1) callMe() メソッドが呼ばれます コードで確認(属性の確認) (2) name 属性を参照 ※this は自身のオブジェクトを 意味しています var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (1) callMe() メソッドが呼ばれます

コードで確認(属性の確認) var obj = { name : “none”, ※this は自身のオブジェクトを 意味しています var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (3) objBlackboxにはname属性がない (1) callMe() メソッドが呼ばれます

コードで確認(属性の確認) var obj = { name : “none”, ※this は自身のオブジェクトを 意味しています var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (3) objBlackboxにはname属性がない (4)__proto__にあるオブジェクトを検索 (objApple) (1) callMe() メソッドが呼ばれます

コードで確認(属性の確認) var obj = { name : “none”, ※this は自身のオブジェクトを 意味しています var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (5) objAppleにnameを発見! (3) objBlackboxにはname属性がない (4)__proto__にあるオブジェクトを検索 (objApple) (1) callMe() メソッドが呼ばれます

コードで確認(属性の確認) var obj = { name : “none”, ※this は自身のオブジェクトを 意味しています var obj = { name : “none”, callMe : function() { alert(“It is ” + this.name); } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var objBlackbox = { }; objBlackbox.__proto__ = objApple; objBlackbox.callMe(); (5) objAppleにnameを発見! (3) objBlackboxにはname属性がない (4)__proto__にあるオブジェクトを検索 (objApple) (1) callMe() メソッドが呼ばれます

あった Object (実体) このように自オブジェクトにない機能 (関数)、属性(変数)に対して __proto__を通して移譲(Delegate) しながらキーが見つかるまで検索して いく仕組み… Dele gate ない Object (実体) Dele gate これが プロトタイプチェイン Object (実体) ない Dele gate Object (実体) ない

__proto__ の役割、ご理解頂けたでしょうか?

ん???、ちょっと待って下さい と思いませんか? __proto__ (別名:[[Prototype]])は内部プロパティだから本来、外部から扱えないもの。 じゃあ、理解できてもこんなコード使えないじゃないか? objApple.__proto__ = obj; と思いませんか?

はい、使わないで下さい!

実は内部的な動作を理解してもらいやすくするために var objApple = { name : “Apple”}; objApple.__proto__ = obj; こんなコードを書きましたが、同等の処理をさせる別の記述があります。

var obj = new Frout(“Apple”); (例)今までのサンプルコードもOOP風に書き換えが必要になってきます。 var Frout = function( pname ) { this.name = pname; } Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; var objApple = new Frout(“Apple”); このコードに関して 後で解説します。

わすれちゃいけない、もう一つのキーワード「prototype」 違いを理解するのがとっても大切!

全ての関数オブジェクトはprototype プロパティを持つ ・Javascriptでは、 全ての関数オブジェクトはprototype プロパティを持つ という仕様があります。 ん? 関数オブジェクト?? 初登場です。 でも安心してください、もう知ってます。

var func = function( ){}; 関数オブジェクトとは こういうの var func = function( ){}; 実は、前述していました。関数であっても「値」として扱える(第一級オブジェクト) というやつです。

では、これが何に使われるのでしょうか・・・ 改めまして、 全ての関数オブジェクトには prototype プロパティ を持ちます。 例えば、 var func = function( ){}; alert( func.prototype ); とすると、undefinedとはならず、prototype プロパティが存在することが確認できます。 でも、関数オブジェクトを定義した直後では、 prototypeは何も値を持たない空っぽのオブジェクトを参照しています。 では、これが何に使われるのでしょうか・・・

オブジェクトが生成されるときに使われます! ちょっと前で触れた new 演算子 で、 オブジェクトが生成されるときに使われます!

objApple.prototype.callMe() コードで確認 (今までのサンプルコードの書き換え版) 次のスライドで触れます var Frout = function( pname ) { this.name = pname; } Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; var objApple = new Frout(“Apple”); objApple.callMe(); コンストラクタの定義 関数オブジェクトを生成。 name変数は未定義。 Frout オブジェクトのprototype プロパティにメソッドを追加 new演算子 でobjApple オブジ ェクトを生成。 objAppleのプロトタイプチェイ ンよりFroutのprototypeを継承 「It is Apple」が出力されます。 objApple.prototype.callMe() ではないことに注目

newした時の処理を擬似的に表現すると var objApple = new Frout(“Apple”); var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj;

newした時の処理を擬似的に表現すると var objApple = new Frout(“Apple”); var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; (1) オブジェクトを生成

newした時の処理を擬似的に表現すると var objApple = new Frout(“Apple”); var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; Frout.prototype にはcallMe メソッドがあります (1) オブジェクトを生成 (2) prototype プロパティを __proto__ に代入

コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数 var objApple = new Frout(“Apple”); newした時の処理を擬似的に表現すると var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; Frout.prototype にはcallMe メソッドがあります (1) オブジェクトを生成 (2) prototype プロパティを __proto__ に代入 (3) コンストラクタ関数を実行 コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数

コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数 var objApple = new Frout(“Apple”); newした時の処理を擬似的に表現すると var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; Frout.prototype にはcallMe メソッドがあります (1) オブジェクトを生成 (2) prototype プロパティを __proto__ に代入 (3) コンストラクタ関数を実行 コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数 (4) 処理したオブジェクトを返す

コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数 var objApple = new Frout(“Apple”); newした時の処理を擬似的に表現すると var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; Frout.prototype にはcallMe メソッドがあります (1) オブジェクトを生成 (2) prototype プロパティを __proto__ に代入 (3) コンストラクタ関数を実行 コンストラクタとは関数オブジェクト生成時に一度だけ呼び出される関数 (4) 処理したオブジェクトを返す var objApple = new Frout(“Apple”);

obj を Frout.prototype だと置き換えたらどちらもcallMe() メソッドを持つことに newした時の処理を擬似的に表現した処理 Frout.prototype.callMe = function() {…}; var obj = { name : “none”, callMe : function() { … } }; var objApple = { name : “Apple”}; objApple.__proto__ = obj; var obj = {}; obj.__proto__ = Frout.prototype; Frout.apply(obj, arguments ); return obj; obj を Frout.prototype だと置き換えたらどちらもcallMe() メソッドを持つことに なることが想像できます。

__proto__ と prototype の違い、ご理解頂けたでしょうか? プロトタイプチェインの検索の仕組みそのもの。 newされたオブジェクトのprototype が自動で格納される。 プロトタイプオブジェクトを格納し、 newされたときに __proto__ に代入されることで プロトタイプチェインを作り出す。 __proto__ prototype 概念の理解のために必要。 実際はnewとprototypeで実装させよう 積極的に使って行きましょう

では、ちょっと頭の体操

var Frout = function( name ) { this.name = name; } Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; と記述しましたが、 var Frout = function( name ) { this.name = name; this.callMe = function() { alert(“It is ” + this.name); }; } と書きたくなりませんか? これじゃダメでしょうか?

OOPの観点から見ると良くないです でも、動きます

理由: var Frout = function( name ) { this.name = name; このコードでは、prototype を使わず、コンストラクタ関数の中で定義されてしまいます。 var Frout = function( name ) { this.name = name; this.callMe = function() { alert(“It is ” + this.name); }; } つまり、 newによりオブジェクトが生成される度にこのメソッド(callMe())も新たに生成されてしまいます。 対照的に、prototype内に定義されたメソッド、変数はプロトタイプチェインの中に入る仕組みに合わせて、 オブジェクトが何度newされても同一のメモリから参照されるという仕組みになっているためメモリ効率がよくなります。 Frout.prototype.callMe = function() { alert(“It is ” + this.name); };

応用

( function () { //関数の中身・・・ }() ); 冒頭で紹介したサンプルコード カッコばかりのこの関数、いったいどういった動作をするでしょう?

結論を先に述べると、 無名関数を作って即時呼び出し を行っています。

関数オブジェクトが返された直後に、その関数を呼び出している。 変数で受けていない無名関数。 即時関数には2つある? //即時関数1 (function () { //関数の中身・・・ }()); //即時関数2 })(); どちらも即時関数として機能しますが、JSLint(http://www.jslint.com/)では 前者のコードの方が好ましいようです。 ( function () { //関数の中身・・・ }() ); 関数オブジェクトを生成。 関数オブジェクトが返された直後に、その関数を呼び出している。 即時関数 というなんとも複雑な処理を経ていました。 ページが読み込まれた時、一度だけ処理をする、といった時に使われます。

応用 その2 …

private 変数だったら参照できないはず OOPと言うのだったらprivate 変数で隠蔽化ぐらいはしたくなりませんか? これって private 変数? protected 変数? public 変数? var Frout = function( name ) { this.name = name; } Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; var objApple = new Frout(“Apple”); alert( objApple.name ); private 変数だったら参照できないはず 結果は…

(当然ながら、)参照できてしまいます orz でもちょっとまって

こんな感じで(魔)改造します var FroutModel = (function() { // private変数 (魔)改造前 var Frout = function( name ) { this.name = name; } Frout.prototype.callMe = function() { alert(“It is ” + this.name); }; var FroutModel = (function() { // private変数 var name = “none"; // コンストラクタ var cls = function(pname){name = pname;}; // public メソッド cls.prototype.callMe = function() {alert("This is "+name);}; return cls; } () );

undefined となり隠蔽化できたことを確認。 var FroutModel = (function() { // private変数 var name = “none"; // コンストラクタ var cls = function(pname){name = pname;}; // public メソッド cls.prototype.callMe = function() {alert("This is "+name);}; return cls; } () ); var objApple = new FroutModel(“Apple”); alert( objApple.name ); objApple.callMe(); undefined となり隠蔽化できたことを確認。 正常に呼び出せます

なんだか大分クラスっぽくなりました。

BaseModel オブジェクトは FroutModel オブジェクトと同様な実装をしているものとします。 ほかにも、クラスっぽい継承もこんなふうに実装出来ます。 var FroutModel = (function() { // private変数 var name = “none"; // コンストラクタ var cls = function(pname){name = pname;}; // 親クラスの継承 cls.prototype = new BaseModel(); // public メソッド cls.prototype.callMe = function() {alert("This is "+name);}; return cls; } () ); こんな感じ。 BaseModel オブジェクトは FroutModel オブジェクトと同様な実装をしているものとします。

var FroutModel = (function() { // private変数 var name = “none"; コードの説明は今までの応用である程度説明できます。是非パズル感覚でチャレンジしてみてください。 (ヒント)スコープチェインのルールによりスコープの外から中は見えない。 var FroutModel = (function() { // private変数 var name = “none"; // コンストラクタ var cls = function(pname){name = pname;}; // 親クラスの継承 cls.prototype = new BaseModel(); // public メソッド cls.prototype.callMe = function() {alert("This is "+name);}; return cls; } () ); (ヒント)FroutModel 関数オブジェクトの中で別関数オブジェクトを生成。 (ヒント) FroutModel 内で生成したオブジェクトを返している。 (ヒント) 即時関数である

今回、 XPagesの話が1つも出ませんでしたが、

今回のJavascriptの内容は クライアントサイドJavascript サーバーサイドJavascript どちらにも通用する概念です。

このオブジェクトの構成をテンプレートとしてJavascript 試しに最後のクラスっぽい実装のオブジェクトをSSJSのスクリプトライブラリにコピペして もそのまま動きます。 var AppModel = (function() { // private変数 var name = “none"; // コンストラクタ var cls = function(pname){name = pname;}; // 親クラスの継承 cls.prototype = new BaseModel(); // public メソッド cls.prototype.func1 = function() {…}; return cls; } () ); 実際に、自分も このオブジェクトの構成をテンプレートとしてJavascript でのOOPに利用しています。

スクリプトライブラリにコピペ

出力結果 XPagesから呼び出し 一旦viewScopeに newしたオブジェクトを 格納しています

XPagesでOOPを利用するときの注意点 viewScopeにnewしたオブジェクトを格納しましたが、 オブジェクトを永続的に保持して利用出来るようにするため、Xspプロパティより「ページをメモリに保存する」を選択します。

いかがでしたでしょうか? Javascriptのオブジェクト指向プログラミングは 理解するまで色々と試してみるのが一番だと思います。 <!DOCTYPE html> <html> <head> <script type="text/javascript"> // <![CDATA[ var FroutModel = (function() { // private variable var name = "hoge"; // コンストラクタ var cls = function(pname){name = pname;}; // メソッド cls.prototype.callMe = function() {alert("This is "+name);}; return cls; }()); var frt = new FroutModel("Banana"); frt.callMe(); alert("frout.name="+frt.name); // ]]> </script> </head> <body> </body> </html> いかがでしたでしょうか? Javascriptのオブジェクト指向プログラミングは 理解するまで色々と試してみるのが一番だと思います。 なんせHTMLファイル1つで試せます。

気づいたらDojoもjQueryももう怖くない、かも

参考 最強オブジェクト指向言語 JavaScript 再入門 株式会社フォーエンキーのノジマ様のスライド http://www.slideshare.net/yuka2py/javascript-23768378 ブログ XPagesで行こう! IBMチャンピオン リコーITソリューションズ株式会社 海老原 賢次さんのブログ https://www.ibm.com/developerworks/community/blogs/ebi/ MDN > 開発者向けのWeb技術 > Javascript Mozilla Developer Network 内のJavascript ポータル https://developer.mozilla.org/ja/docs/Web/JavaScript JSLint バッドプラクティスに対して警告を出す構文チェッカー http://www.jslint.com/

ご清聴ありがとうございました

www.ktrick.com この 文書 は クリエイティブ・コモンズ 表示 - 継承 2.1 日本 ライセンスの下に提供されています。