SlideShare a Scribd company logo
JSer Class
JavaScriptの基礎と軽量フレームワーク
目的
• 一般的観点
• Webアプリケーション開発のなかで存在感を増し続けるJavaScriptに
ついて、「なんとなくわかる」でない知識を身に付ける。
• JavaScriptのメリット、デメリット、代替技術について知ることで、
保守/開発の生産性や品質を向上させる。
• 特殊的観点
• 数カ月後に身近な存在となる某クライアントサイドMVCライクなアプ
リケーションの保守/開発のための基礎知識を得る。
開催概要
• 開催日時
• 3/2(水)〜 毎週水曜 19:30〜21:30 全3回予定
• 会場
• コラボレーションスペース(N・W)
• コンテンツ
• 第1回 JavaScriptの言語仕様
• 第2回 DOMとXmlHttpRequest、軽量フレームワーク
• 第3回 クライアントサイドMVC
参考情報
• サイト
• JavaScriptガイド@MDN
• https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide
• 書籍
• JavaScript 第6版(サイ本)
• http://www.amazon.co.jp/dp/4873115736
• Effective JavaScript
• http://www.amazon.co.jp/dp/4798131113
JSer Class #1
JavaScriptの言語仕様
あらためて
JavaScriptとは何か?
歴史
• その端緒は前世紀末のWWW民間利用解放後のブラウザ競争。
• そのなかで生まれたJavaScriptとJScript、そしてECMAScript。
• 実装と仕様
• JavaScript(実装名) → Netscape社が開発(1995〜)
• JScript(実装名) → Microsoft社が開発(1996〜)
• ECMAScript(仕様名) → Ecma International(旧称・欧
州電子計算機工業会)で策定(1997〜)
• はじめに実装ありき。あり方はSQLと似ている。
現状〜今後
• 当初
• あくまでブラウザ上で何かしらの小規模な処理をこなすための言語
• 数年前(v3〜5)
• Webサイトの高機能化にともないコード量が増大
• ブラウザ間差異の吸収と言語拡張を目的としたライブラリが登場
• 現状(v5.1)
• V8エンジンを独立ランタイムとして転用したNode.jsの登場
• クライアントサイドMVCというデザイン・パターンの登場
• TypeScript、CoffeeScript、ClojureScript、Scala.jsといった代替技術の登場
• 今後(v6〜)
• ???
今、JavaScriptを学ぶ意味
なぜあらためて学ぶ必要があるか? 例えば─
• 活用シーンの多いから。
• ともすえばJavaやC#よりもリーディング力が必要だから。
• TypeScriptなど代替技術(上位技術)の挙動理解に重要だから。
• 「曖昧に済ませられる」言語で「きっちり動く」「メンテしや
すい」アプリをつくるにはテクニックが余計に必要だから。
テキストの構成
• わりと行き当たりばったりに:
かいつまんだJavaScript言語仕様の提示
注意すべきポイント、べき論の提示
サンプルコード、例題コードの提示
• 例題コードについて:
示されるのは極限的状況。
それを解くことを通じて「臭う」コードを見分けられるようになって
ほしい。
JavaScriptには言語仕様上、JavaにおけるようなIDEは存在し得ない。
「自力でコードを読み解く」能力が重要になる。
学び方
• Web上の情報に目を通す
• MDNなど。あくまで入門。体系的理解を期待しないこと。
• 書籍を読む
• 前掲書をおすすめ。
• Webブラウザで試してみる
• ブラウザが内蔵する開発者ツール、Firebugのような拡張機能、
JSFiddleのようなWebサイトを利用する。
JavaScriptにおけるOOP
OOPとは?
• Object Oriented Programming。
• プログラムの処理(関数)とそれに関係性の強いデータとを
「オブジェクト」という単位にまとめることで、プログラムの
生産性を高めようという思想=実践。
• カプセル化は求められていない点に注意。カプセル化はプログ
ラムの疎結合化を推進するための別の思想=実践。FPでも有効
な概念。cf.Haskell、Erlangにおけるエクスポート。
オブジェクト
データ 処理(関数)
補足)FPとは?
• Functional Programming。
• OOPの反対に、関数とデータを完全に切離し、関数の高機能化
をはかることで、プログラムの安全性や保守性の向上、並列分
散処理系実装の容易化を推し進めようとする思想=実践。
• やや「実験場」的で難解。高階関数、クロージャ、ケース式な
どOOPにも応用できる技術が次々と輸出されている。
• 例)Haskell、Erlang、Lisp(およびその方言)
OOPの種類
• クラス・ベースのOOP
• JavaやC#、Python、Rubyなどはこちらに該当
• オブジェクトの「かたち」をクラスであらかじめ宣言
• クラスのかたちでオブジェクト(インスタンス)のかたちも決まる
• プロトタイプ・ベースのOOP
• JavaScriptはこちらに該当(ていうかそれ以外にあるのか?)
• 「かたち」はすべて実行時に動的に決定される
• プロトタイプ(原型)として指定されたオブジェクトがメンバー
(フィールドやメソッド)の継承元となり、それらと自分自身が備え
たメンバーでそのオブジェクトの「かたち」が決まる。
プロトタイプ・チェーン
• あるオブジェクトにメンバ(フィールド/メソッド)が存在す
るか確認する際に利用される概念。
• メンバ検索の順序:
• あるオブジェクトAそのものがメンバを持つかチェック
• オブジェクトAのコンストラクタのprototypeフィールドが指すオブ
ジェクトBがメンバを持つかチェック
• オブジェクトBのコンストラクタのprototypeフィールドが…(中略)
• Object.prototypeが指すオブジェクトXがメンバを持つかチェック
foo bar baz
Foo.prototype Bar.prototype
かたち(型)の扱い方
• 型とは何か?
• プリミティブもオブジェクトも区別せず、味も素っ気もない言い方を
すれば「メモリ上に確保されるサイズとそのフォーマット」。
• 静的型付け
• データには型がある(当たり前)。
• 変数・引数・フィールドにも型がある(これが特徴)。
• 動的型付け
• データには型がある(〃)。
• 変数・引数・フィールドには型がない(これが特徴)。
クラスvsプロトタイプ
静的型付けvs動的型付け
言語 クラスvsプロトタイプ 静的vs動的 ジェネリクス
JavaScript プロトタイプ
動的 ×
Python/Ruby
クラスJava
静的
△(イレイジャ)
C# ○(非イレイジャ)
なぜ動的&プロトタイプになった?
• そもそもは「ちょっとした処理」しか想定していなかった。
• Webサイトはいろいろなリソースの寄せ集め。動的協働のため
には、バージョン問題を惹起するクラスは厄介。
cf.ECMAScript v6における
クラスとモジュール導入。
cf.Erlangにおける動的型付
けの意義。cf. TypeScriptにおける「構
造的部分型」の導入
動的型付けで得られるもの
• ダックタイピングの自由(あるいは責務)
• どんな型のデータでも受け取れる・代入できる、ということは取りも
直さず、どんな型のデータでもきちんと処理できなくてはならない。
この規則に例外はない。
• コンパイラやIDEの助けは得られない。
• 多重定義メソッドからの解放(もしくは追放)
• 受け取るデータの型ごとに多重定義メソッドを宣言しなくてよい。と
いうか、やりたくてもできない。
• コンパイラやランタイムが適切なメソッドを選択してくれていたのと
同じことを、開発者が自分のコードで行わなくてはならない。
プロトタイプベースで得られるもの
• クラスやインターフェース宣言の省略
• どうせ変数が動的型付けなら、データの側もあらかじめかたちが決
まっている必要はない(やや投げやり)。
• メモリの節約
• 継承したいオブジェクトがいるなら、直接プロトタイプとして参照し
てしまえばいい。そうすれば個別インスタンスごとにextendsしたクラ
スのフィールド分までメモリを消費したりしないで済む。
• 代償としてJava/C#にも存在する「継承による強結合」の病弊がもう
一段深刻なかたちで発現する点に注意。
ちょっとまとめ
• JavaScriptはそのビルディング・ブロックからして他のメ
ジャーな言語とはちがう。
• これはそれ自体「悪」というわけではなく、そもそもの目的や
設計思想によるもの。
• しかし利用方法の変化は以下の諸問題を顕在化させた:
• 静的型付けとクラスが提供する事前検証の一切が利用できない
• オーバーロード、ジェネリクスなどの可能性も根本から絶たれている
• IDEはせいぜい予約語の補完くらいしか開発者をサポートできない
• コード量が多くなるにつれてコーディングは煩雑で危険になる
• 複数ソースのスクリプトの混在でセキュリティ・リスクが増大する
オブジェクト・グラフ
基本型(プリミティブ)
• boolean いまさら説明不要。
• number 整数と浮動小数点数の区別はない。
• string 文字列はJava同様イミュータブル。
• null 基本型なのにtypeof nullは”object”を返す。
• undefined 未初期化・未設定を示す。なぜか非予約
語。
特殊値null
• nullという型の唯一の値/インスタンスがnull。
• Javaなどの「オブジェクト参照がない」という意味ではない。
• 定義上変数や配列の要素のスロット、関数の戻り値はあるのだ
が、設定すべき値がないときに、nullを明示的に利用する。
特殊値undefined
• 代入まえの変数、指定されな
かった引数、存在しない添字
アクセスに対する戻り値、
return文のない関数の戻り値
などで登場。
• 強制的に値を生み出したいと
きはvoid演算子を使う。
• 非・予約語なので変数宣言に
より上書きが可能…。
// Java
String hello;
System.out.print(hello);
// JavaScript
var hello;
console.log(hello);
暗黙型変換
• Javaも含む他の多くの言語と同様に暗黙型変換が行われるケー
スがある。しかしその規則はわかりにくい。
• わかりにくい規則を覚えることを考えるまえに、そのような
コーディングを原則禁止とすることを考えるべきである。
• ==演算子は暗黙型変換を生起する。代わりに===を使う。
• ifの条件式、&&や||の被演算子にboolean以外を指定すると暗
黙型変換(ぽい何か)が起こる。以下6値はfalse(ぽい):
• 0, -0, ””, NaN, null, undefined
暗黙型変換
// JavaScript
var a = 0;
var b = ”0”;
var c = + ”0”;
var d = + ”a”;
console.log(a == b); // (1)
console.log(a === b); // (2)
console.log(a === c); // (3)
console.log(a || false); // (4)
console.log(a === NaN); // (5)
この変換方法は非常にしばしば利用さ
れている。しかしdの例が示すように危
険性も大きく、「文字列が数字の並び
だけでできている」という前提なしに
利用してはならない。
暗黙型変換ですらない何か
// JavaScript
var a = 0;
var b = ”0”;
console.log(a || b); // (1)
console.log(b || a); // (2)
console.log(a && b); // (3)
console.log(b && a); // (4)
オブジェクト型(例)
• Object オブジェクト(としか言いようがない何か)
• Array 配列(ないしマップ)
• Arguments 「配列っぽい」オブジェクト
• Function 関数オブジェクト
• RegExp 正規表現オブジェクト
• String 基本型stringに対応するオブジェクト
• Number 基本型numberに対応するオブジェクト
• Boolean 基本型booleanに対応するオブジェクト
JavaScriptのObjectの特徴
• JavaでいえばMap<String,Object>みたいなもの(*)。
• キーと値で表現されるプロパティのセット。
• JavaScriptでは関数もオブジェクトの一種に過ぎないから、
フィールドとメソッドの区別は存在しない。
• Mapと異なるのはプロトタイプ・チェーンを備えていること。
* 類似性の観点でいうと、Typesafe社のTypesafe Configオブジェクトがもっと適当(参考記事:
http://m12i.hatenablog.com/entry/2015/08/17/004038)
オブジェクトの生成(1)
リテラルで記述する
// JavaScript
var foo = { bar: 123, baz: ”456” };
console.log(foo.bar); // (1)
console.log(foo.baz); // (2)
console.log(foo.foo); // (3)
オブジェクトの生成(2)
コンストラクタで記述する
// JavaScript
var Foo = function() {
this.bar = 123;
this.baz = "456";
};
Foo.prototype = { foo: "789" };
var foo = new Foo();
console.log(foo.bar); // (1)
console.log(foo.baz); // (2)
console.log(foo.foo); // (3)
プロパティにアクセスする
A) ドット表記(obj.prop)
B) 添字表記(obj["prop"])
// JavaScript
var obj = { foo: "123", "b a r": 456, "789": "baz" };
console.log(obj.foo); // (A)
console.log(obj["foo"]); // (B)
console.log(obj["b a r"]); // (C)
console.log(obj["bar"]); // (D)
console.log(obj[789]); // (E)
プロトタイプ・チェーン(再掲)
prop0: 123
// JavaScript
console.log(foo.prop2);
console.log(foo.prop3);
foo
// JavaScript
foo.prop2 = 987;
console.log(foo.prop2);
prop2: 987
プロパティ参照時は
チェーンを遡る
プロパティ更新時は
チェーンを遡らない
// JavaScript
var Foo = function() {
this.bar = 123;
this.baz = "456";
};
Foo.prototype = { foo: "789" };
プロトタイプを通じた参照共有
配列の生成と要素アクセス
// JavaScript
var arr = [1, 2, 3];
console.log(arr[1]); // (A)
console.log(arr["1"]); // (B)
arr["2"] = arr["2"].toString();
console.log(arr[2]); // (C)
arr.length = 2;
console.log(arr[2]); // (D)
for ... in 文
• Javaの拡張for文に似ているが、別物。
• inの左辺の変数にはinの右辺のオブジェクトのプロパティ名が
設定される。
• プロパティの検索はプロトタイプ・チェーンを遡って行われる
(toStringなどの組込みプロパティをのぞく)。
• プロパティ名は例え右辺が配列であろうとstring型。
in演算子とhasOwnPropertyメソッド
• in演算子
• あるプロパティ名(左辺)があるオブジェクト(右辺)に存在するか
どうかを判定する。
• 存在判定に際してプロトタイプ・チェーンを遡る。
• hasOwnProperty(String)
• あるプロパティ名(第1引数)があるオブジェクト(レシーバ)に存在
するかどうか判定する。
• 存在判定に際してプロトタイプ・チェーンを遡らない。
String/Number/Boolean
コンストラクタとしての利用は禁止
• ラッパーを使ってオブジェ
クトを生成していはいけな
い。
• メモリの無駄というだけで
なく、同値比較(===)が
機能しない。
// Java
String a0 = ”a”;
String a1 = ”a”;
String a2 = new String(”a”);
// JavaScript
var a0 = ”a”;
var a1 = ”a”;
var a2 = new String(”a”);
ユーティリティとしての利用や
オートボクシングの利用はOK
• Java同様ユーティリティ・ク
ラスとしての機能は便利。
• 基本型に対してメソッド呼び
出しを行うと自動的にラッ
パーが生成され、すぐに破棄
される。
// JavaScript
Number.isNaN(100);
(100).toExponential();
”hello”.replace(”l”, ”r”);
実態はどうあれ仕様上は
stringはあくまでも基本型で
あり、メソッドは持たない。
モンキー・パッチは禁止
• 以下の前提のもとに組込みオブジェクトを「自分好み」に拡張
してしまうこと:
• JavaScriptでは一般に定数もしくは再代入不可の変数をサポートして
いない。
• そしてJavaScriptではオブジェクトの鋳型としてのクラスは存在しな
い(〜v5.1)。
• よって組込みオブジェクトを含むほとんどあらゆるものは変更可能で
ある。
蛇足)Rubyにおけるクラス
• RubyはクラスベースのOOP言語。
• しかしクラスは実行時に動的に拡張することができる。
• それどころか継承ツリーに割り込みをかけることすらできる。
• そしてJavaScript同様標準ライブラリを変更できる。
• この言語の開発者がクラス概念を採用した理由が分からない。
ちょっとまとめ
• JavaScriptのプリミティブ:
• 種類が少なく覚えるのは簡単。
• ただしundefinedやNaNという特殊値の扱いには注意。
• 暗黙型変換はきちんと覚えようとすると大変。
• JavaScriptのオブジェクト:
• 構造的には非常にシンプル。
• ただし曖昧さは無限大。
関数を定義する
オブジェクトとしての関数
• JavaScriptでは関数はオブジェクトである。cf. C#のデリゲート、
Java8のクロージャ、Rubyのブロック。
• したがって関数を格納した配列、関数を引数にとる関数、関数
を戻り値とする関数をつくることができる(高階関数)。
• 関数はそれが定義されたスコープに存在した変数への参照を保
持(束縛)する(後述)。
• 定義方法がいろいろある。
関数を定義する(1)
Functionコンストラクタ関数
• 引数名も関数本体も文字列として渡す。本体はeval()で評価さ
れる。このため関数定義のエンクロージング・スコープを参照
できない。つまりクロージャとなり得ない。
• ふつう使わない。使うべきでもない。
関数を定義する(2)
function文
• その名の通り関数を定義するための文(statement)。
• あるスコープでfunction文で定義された関数は、スコープの他
のすべての手続きが行われる前に評価される(「巻き上げ」と
呼ばれる現象)。つまりコード上より後方で宣言された関数を、
より前方にある手続きで使用できる。なおあるスコープで
function文で定義された関数は、スコープの外からは参照でき
ない。
関数を定義する(3)
匿名function式
• 手続きを表す文ではなく、値を返す式(expression)で定義。
• 式を書ける場所ならどこにでも書ける。
• オブジェクトとしての関数を強調する構文。
関数を定義する(4)
名前付きfunction式
• 3つ目と異なるのは定義された関数に名前が付いており、自分
自身を再帰呼出するときなどに使用できること。
• 仮にエンクロージングスコープで同じ名前が使用されていても
これをシャドウ化する。
• ECMAScript v3仕様/実装では、関数ボディのスコープでプロト
タイプ・チェーンが発生するため危険。使うべきでない。
存在意義の疑われる仮引数(1)
• JavaScriptでは関数の仮引数を宣言できる(当たり前)。
• しかし引数の数はすべて実行時に決まる。
• 仮引数がなくても引数は受け取られる。
• いずれにせよ引数には関数ローカルスコープに自動定義される
argumentsを介してアクセスできる。
• 引数が設定されなかった仮引数にはundefinedが設定される。
存在意義の疑われる仮引数(2)
// JavaScript
var foo = function(arg0, arg1) {
console.log(arg1);};
var bar = function() {
console.log(arguments.length);
console.log(arguments[0]);};
foo(123); // (A)
bar(456); // (B)
bar(456, undefined); // (C)
関数とスコープ
スコープとは?
• 変数/定数が参照できる範囲を制限するもの。スコープ外の変
数や定数を参照することはできない。
• 視点を変えると、ある変数/定数をコード上に記載した時、そ
の変数/定数はスコープという限定された範囲から検索される。
• 同じ名前空間で同じ名前の変数を宣言・代入すれば、上書きが
発生してしまう(Java・C#ではコンパイルエラーになる)。
• スコープはスタック+α。
• スコープがどのような入れ子構造をとるか、どのように生成さ
れるか、どのような寿命を持つか・・・は、言語により異なる。
JavaScriptのスコープ
• グローバル・スコープが存在する。
• 関数がスコープを形成する。
• ブロック・スコープは存在しない。
• パッケージは存在しない。
• スコープの変数≒オブジェクトのプロパティのケースがある。
• スコープが閉じても変数が延命するケースがある。
グローバルスコープが存在する
• <script>タグのすぐ内側や*.jsファイルのすぐ内側。
• スクリプト・ローカルの考え方はないので名前衝突の危険大。
• Java・C#でいえばデフォルトpackageに近い。≠internal
// foo.html
<script type="text/javascript">
var foo = 123;
console.log(foo);
</script>
グローバル・
スコープ
関数がスコープを形成する
• 関数がスコープを形成する。
• そしてこれが明示的にスコープ形成を行う唯一の手段。
• Java・C#におけるthisなしのインスタンス/静的変数参照など
は×。
// JavaScript
var foo = 123;
var bar = function() {
var foo = 456;
};
グローバル・
スコープ
ローカル・
スコープ
スコープ・チェーン
• JavaScriptのスコープ・チェーンは重層構造を持つ。
グローバルスコープ
グローバルで宣言された関数のローカルスコープ
ローカルで宣言された関数のローカルスコープ
ローカルのローカルス
コープで変数が検索され、
存在しなければより外側
のスコープから検索され
る。
変数宣言には必ずvarを使う
// JavaScript
var foo = 123;
var bar = function() {
console.log(foo); // (A)
foo = 456;
console.log(foo); // (B)
var foo = 456;
console.log(foo); // (C)
};
bar();
console.log(foo); // (D)
ブロック・スコープは存在しない
• JavaScriptでは「まるでブロック・スコープがあるかのうよう
な変数宣言」ができる。
• しかしブロック・スコープは存在しない。cf.Java。
// JavaScript
var i = "je";
for (var i in [1,2,3]) {
console.log(i); // (A)
}
console.log(i); // (B)
パッケージは存在しない
• Javaでいうところのpackage、C#でいうところのnamespace、
Rubyでいうところのmoduleといった概念が存在しない。
• 代わりにオブジェクト・プロパティ・チェーンが利用されるこ
とがある。
// JavaScript
var pkg0 = {};
pkg0.pkg1 = {};
pkg0.pkg1.foo = 123;
pkg0.pkg1.bar = function() { ...; };
スコープの変数≒オブジェクトのプロパ
ティというケースがある
• グローバル・スコープで変数宣言することは、windowオブ
ジェクトにプロパティを追加することにほかならない。
• ほかにも「名前付きfnction式」(後述)のような特殊な動きを
するケースがある。
// JavaScript
var foo = 123;
console.log(foo); // (A)
console.log(window.foo); // (B)
スコープ・チェーン(再掲+α)
• JavaScriptのスコープ・チェーンは重層構造を持つ。
グローバルスコープ
グローバルで宣言された関数のローカルスコープ
ローカルで宣言された関数のローカルスコープ
名前付きfunction式の
関数のプロパティ
名前付きfunction式で宣言
された関数では、なぜか
同関数のプロパティがま
ず検索される
ローカルのローカルス
コープで変数が検索され、
存在しなければより外側
のスコープから検索され
る。
スコープが閉じても
変数が延命するケースがある
• 関数が終わればローカル・スコープは閉じる。
• しかし関数Aで定義されたローカル・スコープ(a)内で定義され
た関数Bがあったとき、関数Bで定義されたローカル・スコープ
(b)から(a)の変数αを参照していると、(a)が閉じたあともその
変数だけは引続き延命して、関数B実行のたびに参照・更新が
できる状態になる。
• これを「関数Bが変数αを束縛する」とか「関数Bはクロージャ
である」とか表現する。
スコープが閉じても
変数が延命するケースがある
// JavaScript
var A = function() {
var a = "foo";
var B = function(arg0) {
console.log(a);
a = arg0;
console.log(a);
};
return B;
};
// JavaScript
var B = A();
B("bar"); // (1)
B("baz"); // (2)
var B2 = A();
B2("boo"); // (3)
匿名関数でスコープをつくる
• 匿名関数式で関数を定義して即座にこれを呼び出す。するとグ
ローバル・スコープの汚染/被汚染を気にせずに済む自分だけ
のローカル・スコープを手に入れられる。
// JavaScript
var foo = 123;
(function(){
// anonymous namespace
var foo = 456;
...
})();
ちょっとまとめ
• JavaScriptのスコープは、Javaなどと比べて簡素。
• ようするにグローバルとローカルしか存在しない。
• JavaScriptにはpackageやnamaspaceの概念がない(〜v5.1)
ので「名前空間汚染」は常時・深刻な問題となる。
• 「クロージャ」はJavaの内部クラス同様(それ以上)に便利な
概念。ただしちょっと難解。
• JavaScriptの関数はスコープ・チェーンのかなめとなる。
• スコープ・チェーンにはときどきプロトタイプ・チェーンが関
与する。
コンストラクタとthis
コンストラクタとしての関数
• 関数にnewをつけて呼びだすとコンストラクタとして機能する。
• このとき関数本文内のthisは新しく生成されたオブジェクトを
指す。
// JavaScript
var Foo = function(arg0) { this.bar = arg0; };
var foo = new Foo(123);
console.log(foo.bar); // (A)
Foo(456);
console.log(bar); // (B)
メソッドとしての関数
• オブジェクトのプロパティに設定された関数が、オブジェクト
をレシーバとして実行されるとメソッドとして振る舞う。
• このときthisはレシーバ・オブジェクトを指す。
// JavaScript
Foo.prototype.baz = function() {
console.log(this.bar);
};
var foo = new Foo(123);
foo.baz(); // (A)
// JavaScript
var baz2 = foo.baz;
var bar = 456;
baz2(); // (B)
曖昧なthis(1)
関数の状況 関数の機能(役割)とthisが指すオブジェクト
グローバルスコープ
で定義されたコンス
トラクタ
グローバルスコープで定義された関数で、new演算子ありで実行……関数はコ
ンストラクタ関数として機能。関数はコンストラクタ関数として機能し、this
はObject.prototypeからプロパティを継承する新しいオブジェクトを指す。明
示的にreturn式が実行されない限りこのthisが呼出元に返される。
グローバルスコープ
で定義された関数
グローバルスコープで定義された関数で、new演算子なしに実行……thisは
windowを指す。
プロパティ参照され
たコンストラクタ
オブジェクトのプロパティに設定された関数で、new演算子ありで実行……関
数はコンストラクタ関数として機能。1つ目と同じ。
プロパティ参照され
た関数(メソッド)
オブジェクトのプロパティに設定された関数で、new演算子なしに実行(メ
ソッドとして実行)……thisはオブジェクトを指す。
曖昧なthis(2)
関数の状況 関数の機能(役割)とthisが指すオブジェクト
ローカルで定義され
たコンストラクタ
ローカルスコープで定義された関数で、new演算子ありで実行……関数はコン
ストラクタ関数として機能。1つ目と同じ。
ローカルで定義され
た関数
ローカルスコープで定義された関数で、new演算子なしに実行……thisは
windowを指す。エンクロージングスコープを形成する関数がメソッドであり、
そのthisがメソッドの所属するオブジェクトを指していようとも、そのスコー
プで定義された関数のthisはwindowを指す。
* この2スライドで取り上げた関数のパターンは右の参考記事でも解説している:
http://m12i.hatenablog.com/entry/2013/08/12/000858
*
補足)板挟み状態の再帰関数論
• arguments.calleeは「今呼び出されている関数自体」を指す。
• 過去において再帰関数の定義にはこのプロパティが用いられた。
• しかし現在は代わりに名前付きfunction式を用いるべきとされ
る(*)。これは「末尾再帰最適化」の妨げとなるためだとか。
• ところが名前付きfunction式で宣言された関数のスコープ・
チェーンの最前面には関数オブジェクト自身のプロパティ(プ
ロトタイプから継承したものも含む)が来る(v3)。
• よってこれはこれで危険。再帰関数の実装において、匿名関数
の利用はあきらめるべき・・・か。
* なぜarguments.calleeの利用が非推奨となったかの説明はMDBの右のページに解説がある:
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments/callee
call/applyによるレシーバ差し替え
• 前述のとおり関数内のthisの意味はその宣言方法と呼び出し方
法の組み合わせで決まる。
• ところでJavaScriptには意図的にレシーバ(this)の差し替え
を行う方法が用意されている。
// JavaScript
Foo.prototype.baz = function() {
console.log(this.bar);
};
var foo = new Foo(123);
var obj = {bar: 456};
// JavaScript
foo.baz.apply(obj, []);
関数オブジェク
トへの参照
thisに参照
させたい値
関数の引数
(配列形式)
補足)安全なthis
• 実用的ではないがとにかく安全性を求めなくてはならないケー
スでは、call/applyを使ってthisを無効化する手法をとることが
できる。
// JavaScript
Foo.prototype.baz = function(v) {
this.bar = v;
};
var foo = new Foo(123);
foo.baz.apply(undefined,["456"]);
ちょっとまとめ
• JavaScriptの関数は、関数、メソッド、コンストラクタを兼ね
る。
• thisの扱いはとても微妙で、使いどころに注意する必要がある。
まとめ
まとめ
• 繰り返しになるが「自力でコードを読み解く」能力は重要。
• JavaScriptの言語要素はとても少ない。しかしそれらを組み合
わせたときの挙動は予測しづらい面がある。
• そのためにプロトタイプ・チェーンとスコープ・チェーン、そ
してthisの振る舞いをきちんと理解しておかなくてはならない。
次回は
• 以下の項目について取り上げる予定:
• DOM(Document Object Model) API
• XmlHttpRequestオブジェクト
• 軽量フレームワーク(prototype.js、jQuery)

More Related Content

PDF
JSer Class #3
PDF
JSer Class #2
PDF
JavaScript 研修
PDF
Featuring Project Silk & Liike: 楽しい "モダン" Web 開発のちょっとディープなお話
PDF
大規模なJavaScript開発の話
PPT
Word Press on Movable Type
PDF
Getting start with knockout.js
PDF
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
JSer Class #3
JSer Class #2
JavaScript 研修
Featuring Project Silk & Liike: 楽しい "モダン" Web 開発のちょっとディープなお話
大規模なJavaScript開発の話
Word Press on Movable Type
Getting start with knockout.js
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~

What's hot (19)

PDF
むずかしくないJavaScriptのやさしい話 jQueryからの次のステップ #ndsmeetup8
PDF
はじめよう Backbone.js
PDF
JavaScript MVC入門
PDF
Javascriptのあれやこれやをまとめて説明してみる
PDF
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
PDF
Javaな人が気を付けるべきJavaScriptコーディングスタイル
PDF
TypeScriptへの入口
PDF
モダンJavaScript環境構築一歩目
PDF
XPages Day 2013 [B-3] XPages開発を始める Notes技術者のためのWeb技術概論
PDF
Web制作勉強会 #2
PDF
JavaScriptユーティリティライブラリの紹介
PPTX
T119_5年間の試行錯誤で進化したMVPVMパターン
PPTX
AngularJS2でつまづいたこと
PDF
クライアントサイドjavascript簡単紹介
PDF
JavaScript基礎勉強会
PDF
XPagesDay2013 【B-4】 Dojo 徹底解剖! ~ XPages で Dojo を有効活用するには ~
PDF
Java女子部 Java EEハンズオン(応用編)
PDF
Vue.jsの関連ツール・ライブラリ(Vuex, Vue-Router, Nuxt)
PDF
JSF2.2で簡単webアプリケーション開発
むずかしくないJavaScriptのやさしい話 jQueryからの次のステップ #ndsmeetup8
はじめよう Backbone.js
JavaScript MVC入門
Javascriptのあれやこれやをまとめて説明してみる
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
Javaな人が気を付けるべきJavaScriptコーディングスタイル
TypeScriptへの入口
モダンJavaScript環境構築一歩目
XPages Day 2013 [B-3] XPages開発を始める Notes技術者のためのWeb技術概論
Web制作勉強会 #2
JavaScriptユーティリティライブラリの紹介
T119_5年間の試行錯誤で進化したMVPVMパターン
AngularJS2でつまづいたこと
クライアントサイドjavascript簡単紹介
JavaScript基礎勉強会
XPagesDay2013 【B-4】 Dojo 徹底解剖! ~ XPages で Dojo を有効活用するには ~
Java女子部 Java EEハンズオン(応用編)
Vue.jsの関連ツール・ライブラリ(Vuex, Vue-Router, Nuxt)
JSF2.2で簡単webアプリケーション開発
Ad

Viewers also liked (20)

PPTX
xUnitハンズオン第3回テキスト
PDF
Erlangを触ってみた
PPTX
PDF
GHC 6.12.1 マルチコア対応ランタイムシステムについて
PDF
Yesod(at FPM2012)
PDF
関数型軽い紹介
PDF
第一回関数型言語勉強会 大阪
PPTX
関数型言語初心者の俺がF#触ってみた
PDF
F#で学ぶ関数プログラミング入門?
PDF
FP習熟度レベルとFSharpxのIteratee
PDF
レスポンシブおっぱいでまなぶスケーラブルグラフィックス
PDF
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
PDF
SIMD.js(ECMAScript 7)
PDF
Katagaitai CTF勉強会 #4 Crypto
PDF
これから Haskell を書くにあたって
PPTX
純粋関数型アルゴリズム入門
PDF
120901fp key
PDF
One night Vue.js
PDF
関数型言語とオブジェクト指向言語(序章)
PPTX
xUnitハンズオン第1回テキスト
xUnitハンズオン第3回テキスト
Erlangを触ってみた
GHC 6.12.1 マルチコア対応ランタイムシステムについて
Yesod(at FPM2012)
関数型軽い紹介
第一回関数型言語勉強会 大阪
関数型言語初心者の俺がF#触ってみた
F#で学ぶ関数プログラミング入門?
FP習熟度レベルとFSharpxのIteratee
レスポンシブおっぱいでまなぶスケーラブルグラフィックス
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
SIMD.js(ECMAScript 7)
Katagaitai CTF勉強会 #4 Crypto
これから Haskell を書くにあたって
純粋関数型アルゴリズム入門
120901fp key
One night Vue.js
関数型言語とオブジェクト指向言語(序章)
xUnitハンズオン第1回テキスト
Ad

Similar to JSer Class #1 (20)

PDF
Jubatusでマルウェア分類
PDF
設計/ドメイン設計(4) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第26回】
PDF
サーバサイドエンジニアが 1年間まじめにSPAやってみた
PDF
TypeScript ファースト ステップ (v.0.9 対応版) ~ Any browser. Any host. Any OS. Open Sourc...
PDF
Isomorphic web development with scala and scala.js
PDF
設計/コンポーネント設計(2) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第21回】
PDF
GraphQLはどんな時に使うか
PDF
Scalaプログラミング・マニアックス
PDF
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
PDF
JavaScriptことはじめ
PDF
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
PDF
要求モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第42回】
PDF
Object-Funcational Analysis and design
PDF
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
PDF
Laravelの検索機能の実装方法
PDF
ケーススタディ/テスト 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第47回】
PDF
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
PDF
設計/コンポーネント設計(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第22回】
PDF
Shibuya.lisp #28: 仮題: R について
PDF
PHP Coding in BEAR.Sunday
Jubatusでマルウェア分類
設計/ドメイン設計(4) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第26回】
サーバサイドエンジニアが 1年間まじめにSPAやってみた
TypeScript ファースト ステップ (v.0.9 対応版) ~ Any browser. Any host. Any OS. Open Sourc...
Isomorphic web development with scala and scala.js
設計/コンポーネント設計(2) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第21回】
GraphQLはどんな時に使うか
Scalaプログラミング・マニアックス
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
JavaScriptことはじめ
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
要求モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第42回】
Object-Funcational Analysis and design
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
Laravelの検索機能の実装方法
ケーススタディ/テスト 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第47回】
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
設計/コンポーネント設計(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第22回】
Shibuya.lisp #28: 仮題: R について
PHP Coding in BEAR.Sunday

JSer Class #1