開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質




訳者まえがき

本書をお手にとるような方は既にご存知の通りですが、JavaScriptは「Webブラウザ上で動作するプログラミング言語」というほぼ独占的な地位を長い間守っており、一般へのインターネット普及も手伝って、人気の高いプログラミング言語のひとつとして市民権を得ています。この言語に「触れたことのある」開発者の数を数えると、相当数にのぼるのではと思います。ブラウザ上で動作する別の言語としては、古くはFlash、そして近年はDartなどが開発されていますが、現在のJavaScriptの地位が近いうちに他に脅かされる可能性は少ないでしょう。

ただ、ここ最近に至るまでの「JavaScript」は、DOMと組み合わせたフロントエンド開発に限定されていたといっても過言ではありません。JavaScript言語の持つ様々な癖とブラウザのJavaScript実行環境の微妙な非互換性が融合した結果、独特の環境を醸しだしていて、他の言語やプラットフォームでの開発をおこなう開発者に避けられることもありました。

しかし最近はjQueryなど、ブラウザ上のJavaScript環境の乖離を吸収して便利な機能を提供するライブラリや、リアルタイム通信やWebグラフィックなどを扱うライブラリが次々と登場し、PCブラウザ向けだけではなくHTML5ベースのモバイルアプリを構築する機会が増え、さまざまな用途のためのコーディングパターンが数多く開発されています。JavaScriptをめぐる環境は洗練されてきました。また、Node.jsなどの登場により、フロントエンド以外のシーンでもJavaScriptが利用される機会が増えており、「フロントエンドに関わるため、JavaScriptを避けて通れなかった」から「積極的にJavaScript言語を使って開発」という流れも形成されつつあります。同時に、JavaScriptという言語が持つ力や可能性についても認知が進んでいます。

ブラウザで利用するためのJavaScriptも引き続き重要であることは疑いようがありません。しかし、JavaScriptの実行環境が多様性を増してくると、今後の開発を見据えて「JavaScript言語」の基礎的部分を理解しておくことが重要になります。

本書は、JavaScriptの「オブジェクト」の理解を中心に据えて、JavaScript言語をひと通り経験した方が陥りがちな落とし穴であるthis、プロトタイプチェーン(継承)、スコープチェーンなどをとても簡潔な例でまとめてあります。これらの要素は、今後新しいバージョンのECMAScript/JavaScriptが市場に出てきても、JavaScriptという言語が存在する限り、今までと変わらず決して錆びない要素となるものです。

読み物の分量としてはのボリュームは大きくはありませんが、JavaScript言語で知っておくべきポイントを簡潔にまとめてあるため、本書を読むために使う時間に対する学習効果がとても高いものになっています。JavaScriptをある程度ご存知の方であればどなたに対しても効果はあると思いますが、特に以下のような方に本書を読んでいただくと最大の読書効果を得られると思います。

•jQueryなどのライブラリを通じてJavaScriptの世界に入ったものの、言語仕様にはまだあまり馴染みのない開発者
•他の言語を良く知っていて、JavaScript言語の癖を把握したい開発者

読者のJavaScriptレベルによっては「既に知っている」であろう内容も含まれています。そのような内容の量が多い場合でも少ない場合でも、いままで経験したJavaScriptの理解をより深めることのできる内容となっています。また、JavaScriptという言語を好む開発者の方にとっては、知ることでより楽しくJavaScriptを使うことができるようになるトピックを選んでいます。比較的少ない時間で読める分量ですので、リファレンスのように逆引きで使うよりは、一度全体を通して読み、必要に応じて後日読み返したり、本書の終わり(付録B)に紹介されているような別の書籍でその知識を強化するという方法が効果的であると思います。

日本語版では、原書ではカバーしていない部分であっても、想定される読者に向けてカバーしておくべきと思われる部分について追記を行いました。また、文章とコードを補完する目的で一部の節に図表を差し込みました。

本書を通じて、これまで「なんとなく理解しているような気がする」JavaScriptを心から理解する「目覚め」を経験し、皆様のJavaScriptライフをより豊かにするための要素になれば幸いです。

最後になりましたが、本書の翻訳にあたっては、この機会を与えてくださったオライリー・ジャパンの高恵子さん、そしてレビューに協力していただいた株式会社プログラミングシステム社の里昌紀、高橋英樹、岡本昌樹の各氏に、この場を借りて感謝の意を表したいと思います。

2013年4月
和田 祐一郎

はじめに

本書はJavaScriptのデザインパターンや、JavaScriptによるオブジェクト指向プログラミングの本ではありません。良いJavaScriptの特徴を悪い特徴と区別しているのでもありません。JavaScriptの完全なリファレンスガイドでもありません。プログラミングの超初心者のための本でもなく、JavaScriptを全く知らない人のための本でもありません。レシピ満載のクックブックでもありません。これらの本はすでに存在します。

本書の目的は、JavaScriptにおけるオブジェクトをはじめとするさまざまな要素、たとえばオブジェクトそのものやプリミティブ値、スコープ、継承、グローバルオブジェクトなどを考えることによって、JavaScriptの正確な世界観を提供することです。本書はJavaScriptのオブジェクトの性質について焦点を当てており、ECMA-262 Edition 3標準の簡潔かつ消化可能な要約でもあります。

もしあなたがデザイナーであったり、もしくはjQueryやPrototypeなどのライブラリを介してJavaScriptに接しているフロントエンド開発者であれば、本書を読破することによって「JavaScriptライブラリユーザ」から「JavaScript開発者」に変身することができれば幸いです。

なぜ本書を書いたのか?

最初に認めなければならないのは、本書は私自身のために書いたものだということです。Kool-Aid(粉末ジュース)を飲んでその味をいつも覚えていたいから…。言い換えると、自分の記憶を呼び起こすために自分の言葉で書いたリファレンスがほしかったということです。加えて以下のようなねらいもあります。

・ライブラリの使用は「ブラックボックス症候群」を引き起こします。ライブラリの使用はある場合では有効かもしれませんが、他の場合では有害かくしれません。ライブラリを使うと早く効率的にことを運ぶことができますがこれが「なぜ、どのように、うまく動作しているのかを理解することがありません。「なぜ、どのように」を理解することは、何かがうまくいかなくなった場合や、パフォーマンスに問題が起こった場合に本当に重要です。事実、JavaScriptのライブラリやフレームワークを使ってWebアプリケーション(もしくは単純な登録フォーム)を実装するには、ライブラリだけではなく、その中のエンジンを理解しておく必要があります。本書はそのような場合に自らボンネットをあけて、中のJavaScriptエンジンを触りたいと思う開発者のための本です。

・JavaScript 1.5については、一番up-to-dateでかつ完全なリファレンスガイドをMozillaが提供しています(Mozilla Developer Network: https://developer.mozilla.org/ja/docs/JavaScript)。しかしこのリファレンスには、リファレンスガイドと一緒にあるべき、単一の観点をもって書かれた、「知識」として消化可能な書類が見当たりません。本書はリファレンスガイドが提供しているJavaScriptの仕様を越えて「あなたが知らなければならないこと」のマニュアルになることを目指しています。

・JavaScript1.5は今後も長い期間標準的なJavaScriptとして存在し続けるはずです。たとえ世の中がECMA-262Edition5に移行したとしても、変化しないJavaScriptの礎、エッセンスを書き留めて置きたかったのです。

・高度なレベルのプログラミング言語の本は、巨大なサンプルコードや、意味のない紆余曲折に満たされていることがあります。私は、すぐに動作できるコードとともに書かれた短くポイントを突いた説明を好みます。本書で達成しようとしていることを表す言葉として「技術的な薄切り」という言葉を作りました。複雑なトピックを小さく消化可能なコンセプトに分解し、最小限の文章と、伝えることのみに集中したサンプルコードで説明します。

・世の中に存在する、価値のあるJavaScriptの本は、ほとんどが3インチくらいの厚さを持っています。David Flanaganによるの『JavaScript第6版』(オライリー・ジャパン)は良書ですが、消化するには厚すぎます。徹底的にすべてを説明せずに核心に触れる本を書きたかったのです。

誰が本書を読むべきか?

本書は2種類の人たちをターゲットにしています。最初は、JavaScriptオブジェクトを深く知って、言語への理解を深めたいと思っている一歩進んだJavaScript例級者から中級者です。次に、カーテンの裏を覗いてみたいJavaScriptベテランです。本書はプログラミング初心者や、JavaScript初心者には向いていません。

なぜJavaScript1.5、ECMA-262 Edition 3なのか?

本書はJavaScript 1.5 (ECMA-262 Edition 3 と同等)の仕様にフォーカスしています。現時点で最も広く実装されているバージョンだからです。本書の次のバージョンはECMA-262 Edition5になるでしょう。

なぜDate()、Error()、RegExp()を本書に含めなかったのか?

先に述べたように、本書はJavaScriptのリファレンスガイドではありません。それよりも、JavaScript言語を理解するため、オブジェクトを理解することを中心に構成しています。Date()、Error()、RegExp()は確かに有用なJavaScriptのパーツですが、これらについての理解はJavaScript言語そのものの理解を促進するものではないため、これらのオブジェクトを本書でカバーしないことにしました。本書で得られたものを、これらオブジェクトを含めたJavaScript言語環境一般で活かしてください。

本書を読み始める前に、本書のスタイルを説明しておく必要があります。本書を読み進める上で非常に重要な情報を記載していますので、かならずここを読むようにしてください。

より少ない言葉、より多いコード

本文はコードの補助と位置づけて、サンプルコードをよく読んでください。サンプルコードは千の言葉よりも価値があると信じています。最初に説明を読んで混乱してしまっても心配しないでください。そういう時はサンプルコードを読んで、コードをさわって、コメントを読み返してください。そうすることによって、良いリファレンスへのアクセスさえあればどのようなコードでも書けるレベルの技術を身につけてください。

サンプルコードについて

本書のサンプルコードはjsFiddleを使ってfirebug-lite-devをプラグインとして含めた環境で公開しています(jsFiddleのURLは各サンプルコードに記載してあります)。ただし、一部のコードはjsFiddle環境では動作しないものがあります。そのような場合はサンプルコードのコメントに明記してあります。動作しない場合でもjsFiddleのページにコードを用意してありますので、そのコードをコピーして、ブラウザの開発者用コンソールなどにペーストして実行してください。

なお本書のサンプルコードはすべてグローバルコンテクスト上に記述していることを前提としています。

サンプルコードはほとんどのブラウザ(Developer Consoleなどの開発者用ツール)で正常に動作しますが、古いバージョンのブラウザ(特にIE)を使用している場合、consoleオブジェクト(ログ出力を行うconsole.logなど)が提供されていない場合がありますのでご注意ください。サンプルコードのコメントにconsole.logの出力結果を記述しています。これはjsFiddleの環境をもとにしています。環境によっては出力が異なる場合がありますので注意してください。

また、グローバルオブジェクト名として「window」を明示的に指定しているサンプルコードは、ブラウザ以外の環境(たとえば、Node.isなど)ではコードが動作しない場合があります。グローバルオブジェクトの取り扱い方はそれぞれの実装環境に依存しますので、「window」を適切なグローバルオブジェクトの名前に置き換えることにより大抵の場合は動作します。

本書の表記法

本書では以下の表記法を使います。

太字(サンプル)
強調や新しい用語を示すために使用します。

等幅(sample)
プログラムリストに使用します。本文中でもプログラムの要素を示すために使います。

太字の等幅(sample)
現在説明しているトピックに直接関係している部分を太字にしています。

このアイコンはヒントを示します。

意見と質問

本書の内容については、最大限の努力をもって検証および確認していますが、誤りや不正確な点、誤解や混乱を招くような表現、単純な誤植に気づかれることがあるかもしれません。本書を読んで気づいたことは、今後の版で改善できるように知らせていただければ幸いです。将来の改訂に関する提案なども歓迎します。

株式会社オライリー・ジャパン
電子メール japan@oreilly.co.jp

本書のWebページには、正誤表、サンプルコードなどに関する追加情報を掲載しています。

http://www.oreilly.co.jp/books/9784873116211/

http://shop.oreilly.com/product/0636920027713.do (原著)

オライリーに関するその他の情報については、次のオライリーのWebサイトを参照してください。

http://www.oreilly.co.jp/
http://oreilly.com/

Cody Lindley (著), 和田 祐一郎 (翻訳)
出版社: オライリージャパン (2013/6/19)、出典:出版社HP

目次

訳者まえがき
はじめに.

1章 JavaScript オブジェクト
1.1 オブジェクトの生成
1.2 コンストラクタ関数はオブジェクトインスタンスを構築して返す
1.3 ネイティブ/ビルトインオブジェクトのコンストラクタ
1.4 ユーザ定義の(ネイティブではない)コンストラクタ関数
1.5 new 演算子とコンストラクタ関数でインスタンス生成
1.6 リテラルを使って値を生成
1.7 プリミティブ型(基本型)の値
1.8 null、undefined、’string’、10、true、false はオブジェクトではなくプリミティブ型
1.9 プリミティブ値はどのように保存・複製されるか
1.10 プリミティブ値は、値そのものを比較
1.11 プリミティブ型の文字列、数値、真偽値はオブジェクトのように扱うとオブジェ
クトのようにふるまう
1.12 オブジェクト(複合型の値)
1.13 オブジェクトはどのように保存・複製されるか
1.14 オブジェクトは同値判定に参照を使用
1.15 オブジェクトは動的なプロパティを持つ
1.16 typeof演算子の戻り値
1.17 動的プロパティはミュータブル(可変)オブジェクトする
1.18 すべてのコンストラクタのインスタンスはコンストラク関数にポイントするconstructor プロパティを持つ
1.19 instanceof 演算子を使ってコンストラクタ関数を特定する
1.20 インスタンスは自身のプロパティを持つことができる (インスタンスプロパティ)
1.21 「JavaScript オブジェクト」と「Object() オブジェクト」の意味

2章 オブジェクトとプロパティを扱う
2.1 オブジェクトはすべての値をプロパティとして格納できる
2.2 オブジェクトと配列でツリー構造や多次元配列を実現
2.3 ドット記法とブラケット記法でオブジェクトのプロパティにアクセス
2.4 delete 演算子でプロパティを削除する
2.5 プロパティへの参照はどのように解決されるのか
2.6 hasOwnProperty() を使って、プロパティがプロトタイプチェーン経由ではないことを確認
2.7 in演算子を使って、オブジェクトがプロパティを保持しているかどうかを確認する
2.8 for-in ループを使って、プロパティを列挙する
2.9 ホストオブジェクト
2.10 Underscore.js を使ってオブジェクトを拡張する

3章 オブジェクト (Object())
3.1 Object() オブジェクト
3.2 Object() のパラメータ
3.3 Object() が持つプロパティとメソッド
3.4 Object() のインスタンスのプロパティとメソッド(String.prototype のプロパティ)
3.5 Object() オブジェクトをオブジェクトリテラルで生成する
3.6 すべてのオブジェクトは Object.prototype から継承する

4章 関数 (Function())
4.1 Function() オブジェクト
4.2 Function() のパラメータ
4.3 Function() が持つプロパティとメソッド
4.4 Function() のインスタンスのプロパティとメソッド(Function.prototype のプロパティ)
4.5 関数は常に値を返す
4.6 JavaScript の関数は第一級関数
4.7 関数に引数を渡す
4.8 thisと arguments はすべての関数本体で利用できる
4.9 arguments.callee
4.10 関数インスタンスの length プロパティと arguments.length
4.11 引数を再定義
4.12 関数の実行を中断
4.13 関数の定義方法(宣言、式、もしくはコンストラクタ)
4.14 関数の実行方法(関数、メソッド、コンストラクタ、もしくはcall() とapply())
4.15 無名関数
4.16 関数式を即時実行
4.17 無名関数を即時実行
4.18 関数は入れ子可能
4.19 関数を関数に渡し、関数から関数を返す
4.20 関数宣言を使って、定義される前に関数を実行する(関数の巻き上げ)
4.21 関数は自身を呼ぶ事ができる(再帰)

5章 グローバルオブジェクト
5.1 グローバルオブジェクト
5.2 グローバル関数
5.3 グローバルプロパティ、グローバル変数
5.4 グローバルオブジェクトにアクセスする
5.5 グローバルオブジェクトは暗黙的に参照される.

6章 this
6.1 this とは何か、および this は何を参照するか
6.2 this の値はどのように決められるのか?
6.3 入れ子関数内では、this はグローバルオブジェクトを参照する
6.4 入れ子関数内で this を見失う問題をスコープチェーンを使って回避する。
6.5 call()やapply() を使って this の値をコントロールする
6.6 this キーワードをユーザ定義のコンストラクタ関数で使う
6.7 プロトタイプメソッド内の this は生成されるインスタンスを参照する

7章 スコープとクロージャ
7.1 JavaScript のスコープ
7.2 “JavaScript はブロックスコープを持たない
7.3 関数内で変数を定義する際は常にvar を使い、スコープの穴を避ける
7.4 スコープチェーン(静的スコープ)
7.5 スコープチェーンの検索は最初に発見した値を返す(マスキング)
7.6 スコープは関数実行時ではなく関数定義時に決められる
7.7 クロージャはスコープチェーンによって生成される
7.8 グローバルスコープで宣言されている関数もクロージャである

8章 関数のprototypeプロパティ
8.1 プロトタイプチェーン
8.2 なぜ prototype プロパティが重要なのか
8.3 prototype プロパティはすべての Function() インスタンスに自動的に付与される
8.4 prototype プロパティのデフォルト値は Object() オブジェクト
8.5 コンストラクタ関数から生成されたインスタンスはそのコンストラクタのprototype プロパティにリンクする
8.6 プロトタイプチェーンの終着点は Object.prototype
8.7 プロトタイプチェーンは最初に見つけたプロパティを返す
8.8 prototype プロパティに新しいオブジェクトを設定するとデフォルトのconstructor プロパティを失う
8.9 プロトタイプからプロパティを継承するインスタンスは常に最新の値を取得
8.10 prototype プロパティを新しいオブジェクトに置き換えた場合、 過去のインスタ
ンスは更新しない。
8.11 ユーザ定義コンストラクタもプロトタイプ継承を行うことができる
8.12 継承チェーンを生成する

9章 配列(Array()).
9.1 Array() オブジェクト
9.3 Array() のプロパティとメソッド
9.4 Array() のインスタンスのプロパティとメソッド(Array.prototype のプロパティ)
9.5 配列を生成する
9.6 要素の追加・変更
9.7 length とインデックス
9.8 指定した数の要素を持った配列を生成する
9.9 配列の length を設定して要素の追加・削除
9.10 配列を配列に格納(多次元配列)
9.11 配列の要素を前から・後ろからループする

10章 String()
10.1 String() オブジェクト
10.2 String() で文字列オブジェクトを生成、そして値を文字列に変換
10.3 String() のプロパティとメソッド
10.4 String() のインスタンスのプロパティとメソッド(String.prototype のプロパティ)

11章 Number()
11.1 Number() オブジェクト
11.2 整数と小数
11.3 Number() に引数を渡して数値に変換
11.4 Number() のプロパティとメソッド
11.5 Number() のインスタンスのプロパティとメソッド(Number.prototype のプロパティ)

12章 Boolean()
12.1 Boolean() オブジェクト
12.2 Boolean () のパラメータ
12.3 Boolean() のプロパティとメソッド
12.4 Boolean() のインスタンスのプロパティとメソッド(Boolean.prototype のプロパティ)
12.5 真偽値オブジェクトは格納されている値が false であってもtrue と評価される
12.6 いくつかの値はfalse、それ以外はすべてtrueに変換

13章 プリミティブ型文字列、数値、真偽値
13.1 プリミティブ値は、プロパティにアクセスされるとオブジェクトに変換される
13.2 文字列、数値、真偽値は常にプリミティブ型を使う

14章 null
14.1 null
14.2 typeof null は ‘object’ を返す

15章 undefined
15.1 undefined
15.2 JavaScript ECMA-262 Edition 3 以降ではundefined変数が存在

16章 Math 関数
16.1 ビルトインMathオブジェクト
16.2 Mathが持つプロパティとメソッド
16.3 Mathはコンストラクタ関数ではない
16.4 Mathオブジェクトは変更・削除不可

付録A レビュー

付録B 終わりに

牽引

Cody Lindley (著), 和田 祐一郎 (翻訳)
出版社: オライリージャパン (2013/6/19)、出典:出版社HP