JavaScript復習
今年のゴールデンウィークは10連休だ!
HTML5 + JavaScriptまたはサーバーサイドJavaScriptにそなえて、JavaScriptを勉強しなおしてみる。前者はともかく、後者は、採用が増えたとしてもマイナーなままな気もするが。
Webのサーバ側は、Perl + CGIが当たり前の時代から、サーバやら言語やらフレームワークやら選択肢が増えて、ちらっとためすのもたいへん。サーバーサイドJavaScriptをつかうかどうかも、なにがしかの基準でほかと使い分けになるのだろうか。
JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
- 作者: Douglas Crockford,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/12/22
- メディア: 大型本
- 購入: 94人 クリック: 1,643回
- この商品を含むブログ (190件) を見る
JavaScriptパターン ―優れたアプリケーションのための作法
- 作者: Stoyan Stefanov,豊福剛
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/02/16
- メディア: 大型本
- 購入: 22人 クリック: 907回
- この商品を含むブログ (76件) を見る
上の2冊を駆け足で読んでみた。
The Good PartsとJavaScriptパターンの内容は、重複している点も多かった。JavaScriptパターンは十分コンパクトな内容だったとおもうが、それをさらにコンパクトにしたのがThe Good Partsという印象。
環境構築
JavaScriptの実行環境は、ブラウザなり、ここ最近ちらほら名前を聞くNode.jsなりもある。今回、勉強したいのはAjaxとかサーバーサイドJavaScriptでなくて、それ以前のもっと基本的なことだ。
Javaのjrunscript(Rhino)で、xxxx.jsファイルを実行していく。
println
Rhinoには、ブラウザにダイアログを表示するalertでなくて、コンソール出力してくれるprintlnがある。でも、UTF-8のJavaScriptのファイルを実行したら、日本語が文字化けた。文字化けないようにちょっぴり修正。JavaVMの言語じゃなかったら、自分には、こう簡単には修正できなかったところだ。
var embeded_println = println; var println = function (string, encoding) { var tempString = string + java.lang.System.getProperty("line.separator"); var enc = encoding || "UTF-8"; var bytes = new java.lang.String(tempString).getBytes(enc); java.lang.System.out.write(bytes, 0, bytes.length); };
JavaScriptの特徴
勉強するにつれて「Javaとはぜんぜん違うな」という印象を持つようなった。自分のメインのプログラミング言語はJavaだけど、少なくとも、Javaの知識と照らし合わせないほうが無難そうだ。自分の今の段階の勉強方針としては、Javaとはちがうということをはっきりさせたほうが良さそうだ。
プロトタイプベースのオブジェクト指向言語
- JavaScriptは、Javaのようなクラスベースのオブジェクト指向言語ではない。
- JavaScriptは、プロトタイプベースのオブジェクト指向言語である。
型
typeofを使うと、型がわかる。
js> typeof "1"; string js> typeof 1; number js> typeof null; object js> typeof true; boolean js> typeof println; function js> typeof x; undefined
組み込みで、Object関数がある。Javaには、Objectクラスがあるが、Javaとちがって、JavaScriptにはそもそもクラスというものはない。同じObjectという名前であっても混同してはだめ。まったく別物。Object関数を実行するとオブジェクトを生成できる。
Object関数は、prototypeというプロパティをもつ。このprototypeの型は、objectである。
js> typeof Object; function js> typeof Object.prototype; object js> typeof new Object; object js> typeof new Object(); object js> typeof Object(); object js> typeof {}; object
組み込みで、Function関数がある。Function関数を実行すると関数オブジェクトを生成できる。
Function関数は、prototypeというプロパティをもつ。このprototypeの型は、functionである。
Function関数で生成した関数は、prototypeというプロパティをもつ。このprototypeの型は、objectである。functionではない。
js> typeof Function; function js> typeof Function.prototype; function js> typeof new Function; function js> typeof new Function(); function js> typeof Function(); function js> typeof (new Function()).prototype object js> typeof function(){}; function js> typeof function(){}.prototype; object
文法
デフォルト値の設定
var a; var b = a || "default value"; println(a); println(b);
比較
比較は、
- ===
- !==
でおこなう。
- ==
- !=
は使わないほうがよい。==や!=を使うと、自動の型変換があって、挙動がややこしいらしい。
var
varの有無は、JavaScriptに不慣れなうちは、気づきにくいバグにつながる場合もあるので、注意。
- 関数の外側
- varをつけて宣言した変数
- グローバルオブジェクトのプロパティになる。
- varをつけていない変数
- グローバルオブジェクトのプロパティになる。
- varをつけて宣言した変数
- 関数の内側
- varをつけて宣言した変数
- ローカル変数になる。
- varをつけていない変数
- グローバルオブジェクトのプロパティになる。
- thisが指しているオブジェクトのプロパティになる。
- varをつけて宣言した変数
スコープ
- {....}はスコープにならない。
- if(....) {....} else {....}の{....}はスコープにならない。
- for(....){....}の{....}はスコープにならない。
- while(....){....}の{....}はスコープにならない。
- ある関数の外側か内側かでは、スコープになる。
- function xxxx(....) {....};の{....}はスコープになる。
- ある関数の内側で、varで宣言した変数は、その関数の外側からは見えない。
- ある関数の内側で、宣言した関数は、その関数の外側からは見えない。
- function xxxx(....) {....};の{....}はスコープになる。
名前空間
- Javaのパッケージのようなものは、JavaScriptにはない。
this
thisの挙動はとてもわかりづらい。本を読んでも、実際に実行して試してみても、イマイチわからなかった。あらためまして、なんともだなあ。
- 関数の外側の場合
- thisはグローバルオブジェクトを指す。
- ブラウザだったらwindowとか。
- thisはグローバルオブジェクトを指す。
- 関数の内側の場合
- newをつけないで関数を実行した場合
- thisはグローバルオブジェクト
- thisはこの関数をメソッドにしているオブジェクト
- newをつけて関数を実行した場合
- thisはその関数オブジェクト自身を指す。
- newをつけないで関数を実行した場合
http://bonsaiden.github.com/JavaScript-Garden/ja/:tile
ここにあるthisの例がわかりやすかった。
オブジェクトの生成
ごく単純なオブジェクトの生成
とりあえず、オブジェクトを生成して、後からプロパティをたしていく。
var person = new Object(); person.name = "テスト名"; person.age = 35; person.favoriteThings = ["寿司", "プログラミング"]; person.introdude = function() { var i; for(i = 0; i < this.favoriteThings.length; i++) { println("I love " + this.favoriteThings[i]); } }; person.introdude();
var person2 = { name:"テスト名", age:35, favoriteThings:["寿司", "プログラミング"], introdude:function () { var i; for(i = 0; i < this.favoriteThings.length; i++) { println("I love " + this.favoriteThings[i]); } } }; person2.introdude();
よりJavaScritの機能を活かしたオブジェクトの生成
よりJavaScritの機能を活かしたオブジェクトの生成としては、
- クロージャを活用する。
- prototypeプロパティを活用する。
の2つがある。
関数
関数はひとつのオブジェクトである。宣言するたびにオブジェクトが生成される。宣言のしかたはいろいろ。
継承
JavaScript自身は、プロトタイプベースのプログラミング言語であり、クラスベースのプログラミング言語のような継承はサポートしていない。
継承は、Function関数のprototypeプロパティなどを活かしつつ、ケースバイケースで自分で実現する。面倒なような、柔軟なような。
継承を実現する方法としては、
のようなJavaScriptのライブラリが提供している継承の機能を使ったほうが手間は少ない。