javascript勉強会

40
JꜳꜳS JꜳꜳS JꜳꜳS JꜳꜳS JꜳꜳS JꜳꜳS JꜳꜳS JꜳꜳS 再入門 再入門 再入門 再入門 再入門 再入門 再入門 再入門 2008/05 2008/05 2008/05 2008/05 2008/05 2008/05 2008/05 2008/05 / / / / / / 20 20 20 20 20 20 20 20 ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/ ꜳꜳ ://.ꜳꜳ../ꜳꜳ/

Upload: masakazu-matsushita

Post on 15-Jan-2015

9.917 views

Category:

Technology


2 download

DESCRIPTION

社内で行ったJavaScript勉強会の資料。

TRANSCRIPT

Page 1: JavaScript勉強会

JavaScriptJavaScriptJavaScriptJavaScriptJavaScriptJavaScriptJavaScriptJavaScript 再入門再入門再入門再入門再入門再入門再入門再入門

2008/052008/052008/052008/052008/052008/052008/052008/05////////2020202020202020

matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]matsukaz [http://d.hatena.ne.jp/matsukaz/]

Page 2: JavaScript勉強会

アジェンダ

1. JavaScript概要

2. JavaScriptのオブジェクト

3. 連想配列

4. プロトタイプ

5. 継承

6. クロージャ

7. 参考サイト

Page 3: JavaScript勉強会

1. JavaScript概要

• JavaScriptとは

• JavaScriptとECMAScript

• ECMAScript実装

• ECMAScript関係図

Page 4: JavaScript勉強会

JavaScriptとは

• プロトタイプベースのオブジェクト指向なスクリプト言語

• Netscapeによって開発された

• 開発当初はLiveScriptだったが、Javaの話題性に便乗してJavaScriptという名称に

–言語仕様は似ているがJavaとは関係ない

• Microsoftの実装はJavaScriptに自社技術を追加して拡張したJScript

1. JavaScript1. JavaScript1. JavaScript1. JavaScript概要概要概要概要

Page 5: JavaScript勉強会

JavaScriptとECMAScript

• Ecma Internationalによって策定

• 互換性の低かったJavaScriptとJScriptの標準化を目的に作られたスクリプト言語

–式や構文、基本オブジェクトなどの仕様を決めている

–ブラウザ固有の機能は含められていない

1. JavaScript1. JavaScript1. JavaScript1. JavaScript概要概要概要概要

Page 6: JavaScript勉強会

ブラウザ別ECMAScript実装

ECMAScript 4に等価JavaScript 2.0-

ECMAScript 3に機能追加-Safari

ECMAScript 3に機能追加-Opera 9

JavaScript 1.8に機能追加予定JavaScript 1.9Firefox (次バージョン)

JavaScript 1.7に機能追加JavaScript 1.8Firefox 3.0

JavaScript 1.6に機能追加JavaScript 1.7Firefox 2.0

JavaScript 1.5に機能追加JavaScript 1.6Firefox 1.5

ECMAScript 3に等価JavaScript 1.5Firefox 1.0

ECMAScript 3/Javascript 1.5に等価(JScript 5のバグFix)

JScript 6IE8

ECMAScript 3/Javascript 1.5に等価JScript 5IE6-7

説明名称ブラウザ

出展元:Versions of Javascript((((http://ejohn.org/blog/versions-of-javascript/))))

マイコミジャーナルの記事(マイコミジャーナルの記事(マイコミジャーナルの記事(マイコミジャーナルの記事(http://journal.mycom.co.jp/news/2008/04/25/021/))))

1. JavaScript1. JavaScript1. JavaScript1. JavaScript概要概要概要概要

Page 7: JavaScript勉強会

ECMAScriptECMAScriptECMAScriptECMAScript関係図関係図関係図関係図

出展元:The World of ECMAScript ((((http://ejohn.org/blog/the-world-of-ecmascript/))))

1. JavaScript1. JavaScript1. JavaScript1. JavaScript概要概要概要概要

Page 8: JavaScript勉強会

2. JavaScriptのオブジェクト

• オブジェクトの構成

• 関数

• 高階関数

• コンストラクタ関数

Page 9: JavaScript勉強会

オブジェクトの構成

• JavaScriptのオブジェクトはプロパティのみを持つ

• プロパティにセットできる値もオブジェクト

• 各オブジェクトには自由にプロパティを追加/削除できる

var hogeObj = new Object();

var fugaObj = new Object();

fugaObj.foo = 'fooVal'; // foo プロパティに 'fooVal' をセットhogeObj.fuga = fugaObj; // fuga プロパティに fugaObj をセット

alert(hogeObj.fuga.foo); // 'fooVal' と表示

var hogeObj = new Object();

var fugaObj = new Object();

fugaObj.foo = 'fooVal'; // foo プロパティに 'fooVal' をセットhogeObj.fuga = fugaObj; // fuga プロパティに fugaObj をセット

alert(hogeObj.fuga.foo); // 'fooVal' と表示

2. JavaScript2. JavaScript2. JavaScript2. JavaScriptのオブジェクトのオブジェクトのオブジェクトのオブジェクト

Page 10: JavaScript勉強会

関数

• JavaScriptでは関数もオブジェクト

–プロパティに関数をセットしたものがメソッドとなる

var hogeObj = new Object();

var fugaFunc = function(val){ // 関数を変数として定義alert(val);

}

hogeObj.fuga = fugaFunc; // fuga プロパティに関数をセットhogeObj.fuga('fugaVal'); // 'fugaVal' と表示

var hogeObj = new Object();

var fugaFunc = function(val){ // 関数を変数として定義alert(val);

}

hogeObj.fuga = fugaFunc; // fuga プロパティに関数をセットhogeObj.fuga('fugaVal'); // 'fugaVal' と表示

2. JavaScript2. JavaScript2. JavaScript2. JavaScriptのオブジェクトのオブジェクトのオブジェクトのオブジェクト

Page 11: JavaScript勉強会

高階関数

• 引数に関数を受け取る関数

function hoge(val){ // 関数を定義alert('hello, ' + val);

}

function fuga(array, fn) { // 高階関数for (var i = 0;i < array.length; i++) {

fn(array[i]);

}

}

var array = ['foo', 'bar']; // 配列を定義fuga(array, hoge); // 'hello, foo' 、'hello, bar' と表示

function hoge(val){ // 関数を定義alert('hello, ' + val);

}

function fuga(array, fn) { // 高階関数for (var i = 0;i < array.length; i++) {

fn(array[i]);

}

}

var array = ['foo', 'bar']; // 配列を定義fuga(array, hoge); // 'hello, foo' 、'hello, bar' と表示

2. JavaScript2. JavaScript2. JavaScript2. JavaScriptのオブジェクトのオブジェクトのオブジェクトのオブジェクト

Page 12: JavaScript勉強会

コンストラクタ関数

• コンストラクタ関数でオブジェクトの種類を定義

–全ての関数はコンストラクタ関数となりえる

function Hoge(val){ // コンストラクタ関数this.val = val; // this はこれから生成されるオブジェクトthis.message = function(){ // 無名関数alert(this.val);

}

}

var hogeObj = new Hoge('fugaVal'); // new で Hoge オブジェクトを生成hogeObj.message(); // 'fugaVal' と表示

function Hoge(val){ // コンストラクタ関数this.val = val; // this はこれから生成されるオブジェクトthis.message = function(){ // 無名関数alert(this.val);

}

}

var hogeObj = new Hoge('fugaVal'); // new で Hoge オブジェクトを生成hogeObj.message(); // 'fugaVal' と表示

2. JavaScript2. JavaScript2. JavaScript2. JavaScriptのオブジェクトのオブジェクトのオブジェクトのオブジェクト

Page 13: JavaScript勉強会

3. 連想配列

• 連想配列とは

• オブジェクトと連想配列

Page 14: JavaScript勉強会

連想配列とは

• 配列

–添え字に整数を利用

var array = ['hogeVal', 'fugaVal'];

alert(array[0]); // 'hogeVal' と表示alert(array[1]); // 'fugaVal' と表示

var array = ['hogeVal', 'fugaVal'];

alert(array[0]); // 'hogeVal' と表示alert(array[1]); // 'fugaVal' と表示

• 連想配列

–添え字に文字列を利用

• JavaにおけるHashtableと同じ

var hash = {'hogeKey' : 'hogeVal', 'fugaKey' : 'fugaVal'};

alert(hash['hogeKey']); // 'hogeVal' と表示alert(hash['fugaKey']); // 'fugaVal' と表示

var hash = {'hogeKey' : 'hogeVal', 'fugaKey' : 'fugaVal'};

alert(hash['hogeKey']); // 'hogeVal' と表示alert(hash['fugaKey']); // 'fugaVal' と表示

3. 3. 3. 3. 連想配列連想配列連想配列連想配列

Page 15: JavaScript勉強会

オブジェクトと連想配列

• 全てのオブジェクトは連想配列

–下記オブジェクトは全て同じプロパティを持つ

var obj1 = new Object();

obj1.hogeKey = 'hogeVal'; // 空オブジェクトにプロパティを追加

var obj2 = {'hogeKey' : 'hogeVal'}; // 連想配列を定義

var obj3 = {hogeKey : 'hogeVal'}; // 連想配列を定義(キーは '' で囲まなくても良い)

var obj4 = {};

obj4['hogeKey'] = 'hogeVal'; // 空の連想配列にキーを追加

var obj1 = new Object();

obj1.hogeKey = 'hogeVal'; // 空オブジェクトにプロパティを追加

var obj2 = {'hogeKey' : 'hogeVal'}; // 連想配列を定義

var obj3 = {hogeKey : 'hogeVal'}; // 連想配列を定義(キーは '' で囲まなくても良い)

var obj4 = {};

obj4['hogeKey'] = 'hogeVal'; // 空の連想配列にキーを追加

– こんな指定も可能

var val1 = document.location.protocol;

var val2 = document['location']['protocol']; // プロパティを連想配列のキーで指定

var val1 = document.location.protocol;

var val2 = document['location']['protocol']; // プロパティを連想配列のキーで指定

3. 3. 3. 3. 連想配列連想配列連想配列連想配列

• 呼び出すプロパティを動的変更できるということ

Page 16: JavaScript勉強会

4. プロトタイプ

• prototypeオブジェクト

• 暗黙の参照

• プロトタイプチェーン

• 定義済みオブジェクトの拡張

Page 17: JavaScript勉強会

prototypeプロパティ

• 全ての関数オブジェクトは、prototypeプロパティを保持している

function Hoge(){}

alert(Hoge.prototype != undefined); // trueと表示

function Hoge(){}

alert(Hoge.prototype != undefined); // trueと表示

• prototypeプロパティのデフォルトの参照先は空のオブジェクト

4. 4. 4. 4. プロトタイププロトタイププロトタイププロトタイプ

Hoge.prototype.fuga = 'FugaVal'; // prototypeプロパティの参照先のオブジェクトに// プロパティを設定可能

Hoge.prototype.fuga = 'FugaVal'; // prototypeプロパティの参照先のオブジェクトに// プロパティを設定可能

Page 18: JavaScript勉強会

暗黙の参照

Hoge

fuga = 10

function Hoge(){}

Hoge.prototype.fuga =10;

function Hoge(){}

Hoge.prototype.fuga =10;

var hogeObj1 = new Hoge();

hogeObj1.fuga = 20;

var hogeObj1 = new Hoge();

hogeObj1.fuga = 20;

alert(hogeObj1.fuga); // 20 と表示alert(hogeObj2.fuga); // 10 と表示

alert(hogeObj1.fuga); // 20 と表示alert(hogeObj2.fuga); // 10 と表示

var hogeObj2 = new Hoge();var hogeObj2 = new Hoge();

• オブジェクトが指定したプロパティを持たない場合、そのオブジェクトは生成元のコンストラクタ関数のprototypeプロパティへ暗黙の参照を持つ

4. 4. 4. 4. プロトタイププロトタイププロトタイププロトタイプ

hogeObj1

fuga = 20

hogeObj2

Page 19: JavaScript勉強会

プロトタイプチェーン

• プロトタイプを連鎖させることもできる

Hoge

fuga = 10

var hogeObj = new Hoge();var hogeObj = new Hoge();

alert(fooObj.hoge.fuga); // 10 と表示alert(fooObj.hoge.fuga); // 10 と表示

Foo

hoge = hogeObj

function Hoge(){}

Hoge.prototype.fuga = 10;

function Hoge(){}

Hoge.prototype.fuga = 10;

function Foo(){}

Foo.prototype.hoge = hogeObj;

function Foo(){}

Foo.prototype.hoge = hogeObj;

var fooObj = new Foo();var fooObj = new Foo();

4. 4. 4. 4. プロトタイププロトタイププロトタイププロトタイプ

hogeObj

fooObj

Page 20: JavaScript勉強会

定義済みオブジェクトの拡張

• 定義済みオブジェクトを拡張することもできる

Object.prototype.hoge = 'hogeVal';

var obj = new Object();

alert(obj.hoge); // 'hogeVal' と表示

Object.prototype.hoge = 'hogeVal';

var obj = new Object();

alert(obj.hoge); // 'hogeVal' と表示

Date.prototype.toJPString = function(){

return this.getFullYear() + '年' + (this.getMonth() + 1)

+ '月' + this.getDate() + '日';

}

var date = new Date();

alert(date.toJPString()); // '2008年5月20日' と表示

Date.prototype.toJPString = function(){

return this.getFullYear() + '年' + (this.getMonth() + 1)

+ '月' + this.getDate() + '日';

}

var date = new Date();

alert(date.toJPString()); // '2008年5月20日' と表示

4. 4. 4. 4. プロトタイププロトタイププロトタイププロトタイプ

Page 21: JavaScript勉強会

5. 継承

• 継承とは

• 継承の実装方法

• constructorプロパティ

Page 22: JavaScript勉強会

継承とは

• 継承元で定義された機能を受け継いで、自分自身の機能を追加可能とする仕組み

var person = new Person();

person.getName(); // Person の関数

var person = new Person();

person.getName(); // Person の関数

var emp = new Employee();

emp.getName(); // Person の関数emp.getDept(); // Employee の関数

var emp = new Employee();

emp.getName(); // Person の関数emp.getDept(); // Employee の関数

Person

getName()

Employee

getDept()

5. 5. 5. 5. 継承継承継承継承

Page 23: JavaScript勉強会

継承の実装方法

• JavaScriptとして継承という機能は提供されていない

– JavaScript 2.0(ECMAScript 4)でサポート予定

• プロトタイプチェーンを繋いでいくことで継承らしき実装を実現

– さまざまなパターンの実装方法が存在

• オブジェクトの代入

• プロパティのコピー

• prototypeの代入

5. 5. 5. 5. 継承継承継承継承

Page 24: JavaScript勉強会

継承の実装方法(オブジェクトの代入)

• 継承元のオブジェクトを継承先のprototypeに代入する

function Person(name){this.name = name;}

Person.prototype.getName = function(){return this.name;}

function Person(name){this.name = name;}

Person.prototype.getName = function(){return this.name;}

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.prototype = new Person; // 継承元のオブジェクトを// prototype プロパティに代入

Employee.prototype.getDept = function(){return this.dept;}

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.prototype = new Person; // 継承元のオブジェクトを// prototype プロパティに代入

Employee.prototype.getDept = function(){return this.dept;}

Mozillaやオライリーではこの方法を紹介している。でもオブジェクトを作る目的以外でnewするってどうなの?引数が必須の場合は何を渡

す?コンストラクタ関数内で何らかの処理をしていたら?いろいろ問題が・・・

Mozillaやオライリーではこの方法を紹介している。でもオブジェクトを作る目的以外でnewするってどうなの?引数が必須の場合は何を渡

す?コンストラクタ関数内で何らかの処理をしていたら?いろいろ問題が・・・

Person

getName()

Employee

getDept()

5. 5. 5. 5. 継承継承継承継承

Page 25: JavaScript勉強会

継承の実装方法(オブジェクトの代入)

• 概念図

参照

new

無名オブジェクト

暗黙の参照

new

emp

暗黙の参照

Person

prototype

Employee

prototype

5. 5. 5. 5. 継承継承継承継承

Page 26: JavaScript勉強会

継承の実装方法(プロパティのコピー)

• 継承元のprototypeのプロパティを継承先にコピーする

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.inherit(Person);

Employee.prototype.getDept = function(){return this.dept;}

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.inherit(Person);

Employee.prototype.getDept = function(){return this.dept;}

// 継承元の prototype プロパティを継承先にコピーする関数Function.prototype.inherit = function(superClass){

for(var prop in superClass.prototype){

this.prototype[prop] = superClass.prototype[prop];

}

}

// 継承元の prototype プロパティを継承先にコピーする関数Function.prototype.inherit = function(superClass){

for(var prop in superClass.prototype){

this.prototype[prop] = superClass.prototype[prop];

}

}

個別にプロパティをセットしているので、あとから継承元のprototypeにプロパティを追加

しても反映されない・・・

個別にプロパティをセットしているので、あとから継承元のprototypeにプロパティを追加

しても反映されない・・・

Person

getName()

Employee

getDept()

5. 5. 5. 5. 継承継承継承継承

Page 27: JavaScript勉強会

継承の実装方法(プロパティのコピー)

• 概念図

プロパティのコピー

new

emp

暗黙の参照

Person

prototype

Employee

prototype

5. 5. 5. 5. 継承継承継承継承

Page 28: JavaScript勉強会

継承の実装方法(プロトタイプの代入)

• 継承元のprototypeをオブジェクト化して継承先のprototypeに代入する

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.inherit(Person);

Employee.prototype.getDept = function(){return this.dept;}

function Employee(name, dept){

Person.call(this, name); // 親のコンストラクタ関数呼び出しthis.dept = dept;

}

Employee.inherit(Person);

Employee.prototype.getDept = function(){return this.dept;}

// 継承元の prototype プロパティを継承先の prototype に代入Function.prototype.inherit(superClass){

function Temp(){}

Temp.prototype = superClass.prototype;

this.prototype = new Temp;

}

// 継承元の prototype プロパティを継承先の prototype に代入Function.prototype.inherit(superClass){

function Temp(){}

Temp.prototype = superClass.prototype;

this.prototype = new Temp;

}

一番継承っぽい。あとから継承元のprototypeにプロパティを追加しても反映される。

一番継承っぽい。あとから継承元のprototypeにプロパティを追加しても反映される。

Person

getName()

Employee

getDept()

5. 5. 5. 5. 継承継承継承継承

Page 29: JavaScript勉強会

継承の実装方法(プロトタイプの代入)

• 概念図

new

無名オブジェクト

参照

Person

prototype

Employee

prototype

Temp

prototype参照

暗黙の参照

5. 5. 5. 5. 継承継承継承継承

Page 30: JavaScript勉強会

constructorプロパティ

• オブジェクト名.constructor

–生成元コンストラクタ関数を参照

function Person(name){this.name = name;}

var hoge = new Person('hoge');

alert(hoge.constructor); // Person関数の内容を表示alert(hoge.constructor.name); // Personと表示

function Person(name){this.name = name;}

var hoge = new Person('hoge');

alert(hoge.constructor); // Person関数の内容を表示alert(hoge.constructor.name); // Personと表示

※ constructorのnameプロパティにはIEからはアクセスできない

• 継承の実装次第では、生成元コンストラクタ関数が異なってしまう

–明示的にconstructorプロパティを設定する

Employee.prototype.constructor = Employee;Employee.prototype.constructor = Employee;

5. 5. 5. 5. 継承継承継承継承

Page 31: JavaScript勉強会

6. クロージャ

• クロージャとは

• クロージャの特徴

• クロージャの利用例

• クロージャ利用時の注意点

Page 32: JavaScript勉強会

クロージャとは

• 関数の中で定義された関数

function Hoge(){

this.fuga = function(msg){ // クロージャalert(msg);

}

}

var hogeObj = new Hoge();

hogeObj.fuga('hogeVal'); // 'hogeVal' と表示

function Hoge(){

this.fuga = function(msg){ // クロージャalert(msg);

}

}

var hogeObj = new Hoge();

hogeObj.fuga('hogeVal'); // 'hogeVal' と表示

function hoge(){

function fuga(msg){ // クロージャalert(msg);

}

return fuga;

}

var fugaFunc = hoge();

fugaFunc('fugaVal'); // 'fugaVal' と表示

function hoge(){

function fuga(msg){ // クロージャalert(msg);

}

return fuga;

}

var fugaFunc = hoge();

fugaFunc('fugaVal'); // 'fugaVal' と表示

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 33: JavaScript勉強会

クロージャの特徴

• 関数と、その関数が作られた環境が一体となった特殊なオブジェクト

• 関数の外側で宣言された変数に対する参照を持つ

function Hoge(msg){

var count = 1;

this.fuga = function(){ // クロージャalert(count + ', ' + msg); // count や msg に対する参照を持つcount++;

}

}

var hogeObj = new Hoge('hogeVal');

hogeObj.fuga(); // '1, hogeVal' と表示hogeObj.fuga(); // '2, hogeVal' と表示

function Hoge(msg){

var count = 1;

this.fuga = function(){ // クロージャalert(count + ', ' + msg); // count や msg に対する参照を持つcount++;

}

}

var hogeObj = new Hoge('hogeVal');

hogeObj.fuga(); // '1, hogeVal' と表示hogeObj.fuga(); // '2, hogeVal' と表示

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 34: JavaScript勉強会

クロージャの利用例①

• プライベート関数

–特定のスコープのみで実行可能な関数

• オブジェクト毎に関数オブジェクトが生成されるので、リソースには注意が必要

function Hoge(){

this.fuga = function(){

foo();

}

function foo(){ // クロージャ(プライベート関数)alert('foo');

}

}

var hoge = new Hoge();

hoge.fuga(); // 'foo' と表示

function Hoge(){

this.fuga = function(){

foo();

}

function foo(){ // クロージャ(プライベート関数)alert('foo');

}

}

var hoge = new Hoge();

hoge.fuga(); // 'foo' と表示

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 35: JavaScript勉強会

クロージャの利用例②

• イベント登録

– 各ボタン用のイベントを生成

<form name="form1">

<input type="text" name="text1">

<input type="button" name="button1" value="button1"><br>

<input type="text" name="text2">

<input type="button" name="button2" value="button2">

</form>

選択した値:<span id="disp"></span>

<form name="form1">

<input type="text" name="text1">

<input type="button" name="button1" value="button1"><br>

<input type="text" name="text2">

<input type="button" name="button2" value="button2">

</form>

選択した値:<span id="disp"></span>

document.form1.button1.onclick = dispValue('text1');

document.form1.button2.onclick = dispValue('text2');

function dispValue(target){

return function(){ // 各ボタン用のクロージャを作成disp.innerHTML = document.form1[target].value;

}

}

document.form1.button1.onclick = dispValue('text1');

document.form1.button2.onclick = dispValue('text2');

function dispValue(target){

return function(){ // 各ボタン用のクロージャを作成disp.innerHTML = document.form1[target].value;

}

}

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 36: JavaScript勉強会

クロージャ利用時の注意点

• ループ内でクロージャを作成

–ループ内のクロージャは、関数としては異なるが同じ環境を共有しているため、keyは同じ値になってしまう。

var map = {

'button1' : 'text1',

'button2' : 'text2'

};

for(var key in map){

document.form1[key].onclick = function(){ // ループ内のクロージャdisp.innerHTML = document.form1[map[key]].value; // keyの値に注意が必要

}

}

var map = {

'button1' : 'text1',

'button2' : 'text2'

};

for(var key in map){

document.form1[key].onclick = function(){ // ループ内のクロージャdisp.innerHTML = document.form1[map[key]].value; // keyの値に注意が必要

}

}

ポイントはどうやって共有する環境を切り離すか

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 37: JavaScript勉強会

クロージャ利用時の注意点

• 解決策①(イベント登録を関数で切り離す)

for(var key in map){

(function(n){ // 無名関数内でイベント登録を行うdocument.form1[key].onclick = function(){

disp.innerHTML = document.form1[n].value;

};

})(map[key]);

}

for(var key in map){

(function(n){ // 無名関数内でイベント登録を行うdocument.form1[key].onclick = function(){

disp.innerHTML = document.form1[n].value;

};

})(map[key]);

}

• 解決策②(イベント処理を関数で切り離す)

for(var key in map){

document.form1[key].onclick = (function(n){ // 無名関数内でイベント処理を行うreturn function(){

disp.innerHTML = document.form1[n].value;

}

})(map[key]);

}

for(var key in map){

document.form1[key].onclick = (function(n){ // 無名関数内でイベント処理を行うreturn function(){

disp.innerHTML = document.form1[n].value;

}

})(map[key]);

}

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 38: JavaScript勉強会

クロージャ利用時の注意点

• 解決策③(外部関数化する)

for(var key in map){

document.form1[key].onclick = dispValue(map[key]);

}

// 外部関数で生成した無名関数内でイベント処理を行うfunction dispValue(target){

return function(){ // 各ボタン用のクロージャを作成disp.innerHTML = document.form1[target].value;

}

}

for(var key in map){

document.form1[key].onclick = dispValue(map[key]);

}

// 外部関数で生成した無名関数内でイベント処理を行うfunction dispValue(target){

return function(){ // 各ボタン用のクロージャを作成disp.innerHTML = document.form1[target].value;

}

}

6. 6. 6. 6. クロージャクロージャクロージャクロージャ

Page 39: JavaScript勉強会

7. 参考サイト

• Mozilla Developer Center– http://developer.mozilla.org/ja/docs/JavaScr

ipt

• ECMAScript– http://www.ecmascript.org/

• JavaScript Shell 1.4– http://www.squarefree.com/shell/shell.html

• CodeZineの記事– http://codezine.jp/a/article/aid/220.aspx

• 檜山正幸のキマイラ飼育記– http://d.hatena.ne.jp/m-hiyama/

Page 40: JavaScript勉強会

べつやくメソッド的に言うと・・・

べつやくメソッド用べつやくメソッド用べつやくメソッド用べつやくメソッド用 円グラフ作成君(円グラフ作成君(円グラフ作成君(円グラフ作成君(http://818nc.jp/circle/))))