何の脈絡も無いです、このエントリ。
javascriptでオブジェクト指向って何
javascriptでオブジェクト指向って最初聞いたときは、僕はJavaが最初に習得した言語だったので「あれ、javascriptってprivateもpublicもclassもinterfaceもないじゃん・・・」って思いました。その意味でjavascriptのオブジェクト指向は特殊なようで「クラスもインスタンスも関係ないけど、クラスとインスタンスのような概念を用いたプログラミングがやろうと思えば可能」ということらしい。
javascriptのクラス定義のようなもの
JavaScriptのコンストラクタって関数を定義することっていう理解でおおむね大丈夫のようだ。この関数の中にプロパティをメソッドを持たせれば、クラスのような振る舞いが可能でしょっていうお話。
function sample() { this.name = "sample"; this.hello = function(){return "my name is" + this.name}; } var hoge = new Sample('foo'); hoge.hello();//fooが返される
で、このままだと関数Helloがオブジェクトの数だけ定義されて無駄だから、prototypeを使うといい、と。プロトタイプは全てのオブジェクトが持っているオブジェクト。
sample.protype.hello = function() { return "my name is" + this.name; }//このthisはsampleをさす。
継承
prototypeチェーンを使う。サブクラスのprototypeにスーパークラスのインスタンスを指定すれば、スーパークラスの持っている情報がそのまま引き継がれる。
// Personクラス。メソッドhello()を持つ
function Person() {
}
Person.prototype.hello = function() {
alert("Hello");
};
// ShiraishiはPersonクラスを継承して作りたい
function Shiraishi() {
}
// プロトタイプにPersonのインスタンスを代入する!
Shiraishi.prototype = new Person();
var s =new Shiraishi();
// 継承したメソッドの呼び出し
s.hello();
JavaScriptがプロトタイプベースのオブジェクト指向言語ってどういうこと? - builder by ZDNet Japan
全てのオブジェクトはprototypeというオブジェクトを持っていて、JavaScriptオブジェクトは全てObject.prototypeを基点とした階層構造になっているので、こういうprototypeによる連鎖が可能。プロパティを継承する場合は親クラスのコンストラクタを自分のクラスから呼び出すことで行う。これを行うにはfunction.applyを使う。
function oya(name) { this.name = name; } function ko(name) { //oyaオブジェクトのoyaコンストラクタをkoが参照して呼び出す。 oya.apply(this,[name]); } var hoge = ko('test'); console.log(hoge.name);
なんか微妙だ。oyaにアクセサ設けたくなる。
オーバーロード、オーバーライド
Javaだと「オーバーロード」「オーバーライド」がありますが、javascriptにはございません。
呼び出されたfunctionの中で引数を判断して処理を振り分ける。かといってargumentsプロパティで「return arguments[2] == undefined ? hoge() :foo()」とかやるとめっちゃわかりにくいので、引数の存在チェックには使っていいけどロジックの起点に使うのはやめといたほうがよい。
オーバーライドは単なる上書きになります。javascriptでは同名の関数はあとで書いた関数が優先されます。
オブジェクトへの参照
オブジェクトのプロパティ存在チェックは否定演算子を使う。nullやundefinedの変数に対して論理演算子をかますと自動的にfalseになる言語仕様らしい。存在すればtrue。
javascriptはJavaと違って関数渡して関数を返すなんてことができる。javascriptは関数もオブジェクト。オブジェクトのプロパティとして関数を保有することが可能で、文字列でそのプロパティに参照できる。よって、こういうことが可能。
JavaScriptのイロハ:「関数はオブジェクト」って理解できますか? - builder by ZDNet Japanより
var s1 = "al"; var s2 = "ert"; window[s1 + s2]("Hello, World");
このコードはjavascriptのオブジェクトについて理解を深めるのに絶好のサンプルだと思う。うおおおって僕は思った。また、文字列をjavascriptのコードとして扱うことも出来る。eval()っていう関数がそれ。
console.log(eval("4*10")); console.log(eval("alert('test')"));
Java6からこういうこともできるようになったらしい。JavaからJSよんでEvalできる。どーゆー局面で誰が使うんだこれ。
JavaからJavaScriptを呼び出すサンプル - 昼間のメモ
配列
javascriptの配列は簡単に言えば全部ハッシュテーブル。インデックスでもキーでも参照可能。あと、これ。かっこよくてコーヒーふいた。
従って、JavaScript配列のlengthプロパティは「配列にどれだけ値が格納されているか」を表すものではありません。結論を言うとlengthプロパティは、「インデックス最大値 + 1」を表す値で自動的に更新される特殊なプロパティなのです。「lengthはヘンなプロパティである」という意味がお分かりいただけたのではないでしょうか。
JavaScriptの配列をも~っと深く理解する:lengthの不思議な動作 - builder by ZDNet Japan
なんだってー!!!!
var ary=[1,2,3]; alert(ary.length);//3が表示される。 ary[100] = 4; idx = 0; for(var i in ary) { idx++;console.log(i);} console.log(idx);//idxが35になった。
で、iの中身にはarrayのfunctionのオブジェクトが入っていた。sortとかreverseとか。よって、配列に入っている要素数を正しく検知する際には注意が必要。この100ってのは、あたかも100個の要素のように見えるけど、実は単なるキー。javascriptでは数値もキーとして扱うことが出来、非常にわかりにくくなっているわけで・・・。配列の添え字はハッシュのキーでしかないようだ。
クロージャ
こういうやつ。
function hoge() { var i = 0; function foo() { i++; return i; } return foo; } var bar = hoge(); bar();//1 bar();//2 bar();//3 var unk = hoge(); unk();//1
はじめ見たときは関数をネストしてるだけじゃんって思ったんだけど何が違うかというと、関数とローカル変数の状態の参照を保持できるってことなのな。ある関数の中で定義された状態(環境)をローカル変数も含めてそっくりそのままコピーできるのがクロージャと呼ばれるものらしい。
次はdomやajaxあたりについて書くつもり。