SlideShare a Scribd company logo
2013/4/27 @ HC社内勉強会
JavaScript
の落とし穴
今日話すこと
普通のOOPL経験者から見た
コアJSのハマりどころ
→ 基礎的な話
→ イディオムの理解
基礎編
JSのオブジェクトは
連想配列みたいなもの
1 // 空のオブジェクトを作成
2 var dog = {};
3
4 // プロパティをひとつ追加
5 dog.name = "Pochi";
6
7 // ブラケットでもアクセスできる
8 dog['breed'] = "Shih Tzu";
9
10 // 関数をひとつ追加 -> メソッド
11 dog.getBreed = function () {
12 return this.breed;
13 }
JSのオブジェクトは
連想配列みたいなもの
1 // 同じものをオブジェクトリテラルで表記
2 var dog = {
3 name: "Pochi",
4 breed: "Shih Tzu",
5 getBreed: function () {
6 return this.breed;
7 }
8 };
クラスっぽいものと
コンストラクタ関数
1 // Stringはコンストラクタなのか?
2 var str1 = new String(123);
3 console.log(str1); // "123"
4
5 // 関数? それともキャスト???
6 var str2 = String(456);
7 console.log(str2); // "456"
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
クラスっぽいものと
コンストラクタ関数
1 // クラスっぽいものを作るコンストラクタ
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // new をつけて呼び出す
10 var adam = new Person("Adam");
11 console.log(adam.say()); //"I am Adam"
12
13 // new をつけずに呼び出す
14 var eve = Person("Eve");
15 console.log(eve); //undefined!
オブジェクト
this
name : Adam
say : {...}
adam
関数のnew呼び出し
明示的な指定呼び出し
メソッド呼び出し
それ以外(グローバル)
第一の鬼門、
this
明示的な指定呼び出し
1 var prop = "gProp";
2 var obj = {prop : "rProp"};
3
4 var func = function (str) {
5 console.log(this.prop + "::" + str);
6 };
7
8 func("normal"); // gProp::normal
9 func.call(obj, "call"); // rProp::call
10 func.apply(obj, ["apply"]); // rProp::apply
メソッド呼び出し
1 var prop = "gProp";
2 var obj = {
3 prop : "rProp",
4 func : function (str) {
5 console.log(this.prop + "::" + str);
6 }
7 };
8
9 obj.func("dot"); // rProp::dot
10 obj['func']("bracket"); // rProp::bracket
11
12 var func2 = obj.func;
13 func2("func2"); // gProp::func2
第二の鬼門、
暗黙の型変換
1 '100' - 1; // 99
2 '100' - '1'; // 99
3 '100' + 1; // “1001”
4 1 + '100'; // “1100”
5 typeof +'100'; // “number”
6
7 // null,undefined,0,-0,NaN,"" はfalse扱い
8 var b = new Boolean(false);
9 if (b) {/* 実行される */}
10
11 var n = new Number(0);
12 if (n) {/* 実行される */}
第二の鬼門、
暗黙の型変換
1 function Person (name, age) {
2 this.name = name || "Guest";
3 this.age = age || 20;
4 }
5
6 // {name:"Guest", age:20}
7 var p1 = new Person();
8
9 // {name:"Baby", age:20} になってしまう
10 var p2 = new Person("Baby", 0);
1 "Str" == "Str"; // true. ★型が同じ場合
2 null == undefined; // true.
3 10 == "1e+1"; // true. ★数値と文字列
4 true == 1; // true. ★Booleanと数値。数値で比較される!
5 true == 10; // false.
6 false == 0; // true.
7 true == "0x01"; // true. ★Booleanと文字列。数値比較
8 false == "0e+0"; // true.
9 100 == {}; // false. ★数値とオブジェクト。数値比較
10 123 == { // true.
valueOf:function(){return 123}};
11 "Str" == {}; // false. ★文字列とオブジェクト
12 "Str" == { // true
toString:function(){return "Str"}};
13 {} == true; // false. ★その他 if ({}) {実行される}
14 {} == false; // false.
同値演算子 == と ===
JavaScriptの落とし穴
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
問題2:
c1は、
prototypeというプロパティを持つ。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
第三の鬼門、
プロトタイプチェーン
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
というコードがあるとき、
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3 c1.constructor === Child; // true
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3 c1.constructor === Child; // true
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3 c1.constructor === Child; // true
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3 c1.constructor === Child; // true
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
1 var Child = function (name) {this.name = name;};
2 var Parent = function (name) {this.name = name;};
3 Child.prototype = new Parent("Adam");
4
5 var c1 = new Child("Cain");
6 Parent.prototype.getName = function () {return this.name;};
7 c1.getName(); // “Cain”.
Child
Child
proto
Parent
Parent
proto
AdamCain
メソッド
getName
Object
Object
proto
toString
valueOf
etc...
メソッドはprototypeに
1 // クラスっぽいものを作るコンストラクタ(修正前)
2 var Person = function (name) {
3 this.name = name;
4 this.say = function () {
5 return "I am " + this.name;
6 };
7 };
8
9 // 修正後
10 var Person2 = function (name) {
11 this.name = name;
12 };
13
14 Person2.prototype.say = function () {
15 return "I am " + this.name;
16 };
暗黙じゃない環境もある
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3
4 c1.__proto__ === Child.prototype; // 環境依存でtrue
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
Object
c1
__proto__:
name: Cain
暗黙じゃない環境もある
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
3
4 c1.__proto__ === Child.prototype; // 環境依存でtrue
Function
Child
prototype:
Object
無名
constructor:
Object
c1
name: Cain
Object
c1
__proto__:
name: Cain
Child
AdamCain
Parent
Parent
proto
あくまでオブジェクトの
チェーンである
EveAbel
Seth
Child
AdamCain
Parent
Parent
proto
あくまでオブジェクトの
チェーンである
EveAbel
Seth
Child
AdamCain
Parent
Parent
proto
あくまでオブジェクトの
チェーンである
EveAbel
Seth
Child
AdamCain
Parent
Parent
proto
あくまでオブジェクトの
チェーンである
EveAbel
Seth
Child
AdamCain
Parent
Parent
proto
あくまでオブジェクトの
チェーンである
EveAbel
Seth
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
×
Child
prototype
無名
constructor
c1
__proto__
1 var Child = function (name) {this.name = name;};
2 var c1 = new Child("Cain");
問題1:
c1のプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
○
問題2:
c1はprototype
というプロパティをもつか。
○か×か?
問題3:
Child.prototypeと
c1.__proto__は
同じオブジェクトを参照する。
○か×か?
(ただし環境に依る)
無名
constructor
Function
prototype
call()
apply()
etc...
問題4:
Childのプロトタイプオブジェクトは
Child.prototypeが
参照するオブジェクトである。
○か×か?
継承は手段のひとつ
コードの再利用こそが目的
継承にはいくつも方法がある
Object.create();
委譲、ミックスイン
最後の鬼門、
スコープチェーン
1 var temp1 = "grobal1";
2 var temp2 = "grobal2"
3 console.log(temp1); // "grobal1"
4 console.log(temp2); // "grobal2"
5
6 func();
7 function func () {
8 console.log(temp2); // "grobal2"
9 var temp1 = "local";
10 console.log(temp1); // "local"
11
12 if (true) {
13 console.log(temp1); // "local"
14 var temp1 = "if";
15 console.log(temp1); // "if"
16 }
17 console.log(temp1); // "if"
18 }
19
20 console.log(temp1); // "grobal1"
1 var temp1 = "grobal1";
2 var temp2 = "grobal2"
3 console.log(temp1); // "grobal1"
4 console.log(temp2); // "grobal2"
5
6 func();
7 function func () {
8 console.log(temp1); // undefined
9 console.log(temp2); // "grobal2"
10 var temp1 = "local";
11 console.log(temp1); // "local"
12 }
13
14 console.log(temp1); // "grobal1"
15 console.log(temp2); // "grobal2"
変数の巻き上げ
1 var func1 = function () {
2 console.log(arg); // undefined
3 var arg = "local";
4 };
5
6 var func2 = function () {
7 var arg = undefined;
8 console.log(arg); // undefined
9 arg = "local";
10 };
変数の巻き上げ
1 func("one"); // "one"
2 func(); // undefined
3 func("one", "two", "three"); // "one"
4
5 function func (arg1) {
6 console.log(arg1);
7 }
もう少し詳しい理解
1 func("one"); // "one"
2 func(); // undefined
3 func("one", "two", "three"); // "one two three"
4
5 function func (arg1) {
6 console.log(arg1);
7
8 for (i = 1; i < arguments.length; i++) {
9 console.log(arguments[i]);
10 }
11 }
もう少し詳しい理解
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
globalオブジェクト
f : function{...}
x : xxx1 var x = "xxx";
2 f(100, 200, 300);
3
4 function f(a1) {
5 var y = "yyy";
6 g(200);
7
8 function g(a1) {
9 console.log(z); // undefined
10 console.log(y); // "yyy"
11 console.log(x); // "xxx"
12 var z = "zzz";
13 }
14 }
Callオブジェクト
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : undefined
g : function{...}
fのCallオブジェクト
arguments : [...]
a1 : arguments[0]
y : yyy
g : function{...}
gのCallオブジェクト
arguments : [...]
a1 : arguments[0]
z : undefined
レキシカル(字句的)スコープ
1 var x = 100;
2 var y = 200;
3
4 f();
5
6 function f () {
7 var y = 20;
8 g();
9 }
10
11 function g () {
12 var z = 3;
13 console.log(x); // 100
14 console.log(y); // ???
15 console.log(z); // 3
16 }
globalオブジェクト
プロパティは省略
fのCallオブジェクト
プロパティは省略
gのCallオブジェクト
プロパティは省略
関数fの
スコープチェーン↓
関数gの
スコープチェーン↓
レキシカル(字句的)スコープ
1 var x = 100;
2 var y = 200;
3
4 f();
5
6 function f () {
7 var y = 20;
8 g();
9 }
10
11 function g () {
12 var z = 3;
13 console.log(x); // 100
14 console.log(y); // ???
15 console.log(z); // 3
16 }
globalオブジェクト
プロパティは省略
fのCallオブジェクト
プロパティは省略
gのCallオブジェクト
プロパティは省略
関数fの
スコープチェーン↓
関数gの
スコープチェーン↓
レキシカル(字句的)スコープ
1 var x = 100;
2 var y = 200;
3
4 f();
5
6 function f () {
7 var y = 20;
8 g();
9 }
10
11 function g () {
12 var z = 3;
13 console.log(x); // 100
14 console.log(y); // ???
15 console.log(z); // 3
16 }
globalオブジェクト
プロパティは省略
fのCallオブジェクト
プロパティは省略
gのCallオブジェクト
プロパティは省略
関数fの
スコープチェーン↓
関数gの
スコープチェーン↓
レキシカル(字句的)スコープ
1 var x = 100;
2 var y = 200;
3
4 f();
5
6 function f () {
7 var y = 20;
8 g();
9 }
10
11 function g () {
12 var z = 3;
13 console.log(x); // 100
14 console.log(y); // ???
15 console.log(z); // 3
16 }
globalオブジェクト
プロパティは省略
fのCallオブジェクト
プロパティは省略
gのCallオブジェクト
プロパティは省略
関数fの
スコープチェーン↓
関数gの
スコープチェーン↓
スコープチェーンまとめ
スコープは2種類存在する
→ letってのもあるけど割愛
変数の巻き上げに注意する
関数呼び出しで
Callオブジェクトが生成される
関数のスコープチェーンは
関数の定義位置で決まる
ちょっとだけ
イディオム編
JSには以下の機能を
実装するための構文がない
名前空間
モジュール、パッケージ
アクセス修飾子(private)
即時関数パターン
1 (function () {
2
3 var days = ['日','月','火','水','木','金','土'];
4 var day = new Date();
5 console.log(days[day.getDay()] + ',' + day.getDate());
6
7 })(); // "土,27"
1 var func = function () { // 関数の宣言
2 /* 関数の中身 */
3 };
4
5 func(); // 関数の実行
クロージャ
クロージャ(クロージャー、closure、閉包)はプログ
ラミング言語における関数オブジェクトの一種。いくつ
かの言語ではラムダ式 (Lambda Expression) や無名関
数 (Anonymous function) で実現している。引数以外
の変数を実行時の環境ではなく、自身が定義された環境
(静的スコープ)において解決することを特徴とする。
関数とそれを評価する環境のペアであるともいえる。
クロージャ
クロージャ(クロージャー、closure、閉包)はプログ
ラミング言語における関数オブジェクトの一種。いくつ
かの言語ではラムダ式 (Lambda Expression) や無名関
数 (Anonymous function) で実現している。引数以外
の変数を実行時の環境ではなく、自身が定義された環境
(静的スコープ)において解決することを特徴とする。
関数とそれを評価する環境のペアであるともいえる。
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
1 var makeFunc = function (base) {
2 var step = 10;
3 var count = 0;
4
5 return function (arg) {
6 var result
7 = base + step * count + arg;
8 count++;
9 return result;
10 }
11 }
12
13 var c1 = makeFunc(500);
14 console.log(c1(3)); // 503
15 console.log(c1(6)); // 516
16 console.log(c1(9)); // 529
globalオブジェクト
プロパティは省略
makeFuncのCO
base : 500
step : 10
count : 0
c1のCO
まだ生成されてない!
c1のCO 一回目
arg : 3
makeFuncのCO
base : 500
step : 10
count : 1
c1のCO 二回目
arg : 6
privateの実現
1 function Animal(arg) {
2 // 以下、プライベート
3 var name = arg;
4
5 // 以下、パブリック
6 this.getName = function () {
7 return name;
8 };
9 }
10
11 var dog = new Animal("dog");
12
13 console.log(dog.name); // undefined
14 console.log(dog.getName()); // "dog"
Callオブジェクトが分かれば
大体のイディオムは分かる
即時関数パターン
→ 一時的な変数をCallオブジェクトに閉じ込める
クロージャ
→ 関数定義時の環境(状態)をSCに閉じ込める
privateメンバ
→ 隠蔽したい変数をCallオブジェクトに閉じ込める
名前空間、モジュール等は
以下の書籍で
おまけ
JavaScriptの落とし穴
JavaScriptの落とし穴
JavaScriptの落とし穴
その他、良さげな理由
静的型付け + 型推論
ECMAScript6準拠
IDEとの連携
開発が活発
というわけで、
TypeScriptやろうぜ!
ご清聴ありがとうございました

More Related Content

What's hot (20)

PDF
圏論のモナドとHaskellのモナド
Yoshihiro Mizoguchi
 
PDF
GoによるWebアプリ開発のキホン
Akihiko Horiuchi
 
PDF
Minecraft による強化学習の実践 (MineRL)
Tusyoshi Matsuzaki
 
PDF
ドメインモデルの育て方
増田 亨
 
PDF
【Unity】Scriptable object 入門と活用例
Unity Technologies Japan K.K.
 
PDF
最強オブジェクト指向言語 JavaScript 再入門!
Yuji Nojima
 
PDF
【メタサーベイ】基盤モデル / Foundation Models
cvpaper. challenge
 
KEY
やはりお前らのMVCは間違っている
Koichi Tanaka
 
PDF
例外設計における大罪
Takuto Wada
 
PDF
中3女子でもわかる constexpr
Genya Murakami
 
PDF
Marp Tutorial
Rui Watanabe
 
PDF
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
shinjiigarashi
 
PPTX
BoostAsioで可読性を求めるのは間違っているだろうか
Yuki Miyatake
 
PDF
イマドキC++erのモテカワリソース管理術
Kohsuke Yuasa
 
PDF
規格書で読むC++11のスレッド
Kohsuke Yuasa
 
PDF
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
日本マイクロソフト株式会社
 
PPT
Glibc malloc internal
Motohiro KOSAKI
 
PPTX
最速C# 7.x
Yamamoto Reki
 
PDF
テスト文字列に「うんこ」と入れるな
Kentaro Matsui
 
PDF
Dockerfileを改善するためのBest Practice 2019年版
Masahito Zembutsu
 
圏論のモナドとHaskellのモナド
Yoshihiro Mizoguchi
 
GoによるWebアプリ開発のキホン
Akihiko Horiuchi
 
Minecraft による強化学習の実践 (MineRL)
Tusyoshi Matsuzaki
 
ドメインモデルの育て方
増田 亨
 
【Unity】Scriptable object 入門と活用例
Unity Technologies Japan K.K.
 
最強オブジェクト指向言語 JavaScript 再入門!
Yuji Nojima
 
【メタサーベイ】基盤モデル / Foundation Models
cvpaper. challenge
 
やはりお前らのMVCは間違っている
Koichi Tanaka
 
例外設計における大罪
Takuto Wada
 
中3女子でもわかる constexpr
Genya Murakami
 
Marp Tutorial
Rui Watanabe
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
shinjiigarashi
 
BoostAsioで可読性を求めるのは間違っているだろうか
Yuki Miyatake
 
イマドキC++erのモテカワリソース管理術
Kohsuke Yuasa
 
規格書で読むC++11のスレッド
Kohsuke Yuasa
 
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
日本マイクロソフト株式会社
 
Glibc malloc internal
Motohiro KOSAKI
 
最速C# 7.x
Yamamoto Reki
 
テスト文字列に「うんこ」と入れるな
Kentaro Matsui
 
Dockerfileを改善するためのBest Practice 2019年版
Masahito Zembutsu
 

Viewers also liked (20)

PDF
5分で分かるgitのrefspec
ikdysfm
 
PPTX
Jenkins+Gitによる検証済みマージ(30分版)
Kohsuke Kawaguchi
 
PDF
GitHub入門 手順編
hideaki honda
 
PDF
やはりお前らのiOS7対応は間違っている
今城 善矩
 
PDF
査読の仕組みと論文投稿上の対策
Takayuki Itoh
 
PDF
HTML5ハイブリッド アプリ開発の実践〜開発現場ですぐに活かせるコツを伝授〜
Monaca
 
PDF
Xcodeを便利に使って爆速開発する #yxcm
Hiramatsu Ryosuke
 
PDF
iOS アプリのメンテナンス性を高めるための基本的な考え方
kakegawa-atsushi
 
PDF
Chrome Developer Toolsを使いこなそう!
yoshikawa_t
 
PDF
はやわかりHTML5ハイブリッドアプリ開発事情
Monaca
 
PDF
ネイティブとHTML5を スマートに連携させる設計と 実装のノウハウについて
Kazuaki Hidaka
 
PDF
数式を綺麗にプログラミングするコツ #spro2013
Shuyo Nakatani
 
PDF
pythonでオフィス快適化計画
Kazufumi Ohkawa
 
PDF
ソフトウェア設計のすすめ
Yoshimura Soichiro
 
PPTX
非同期処理の基礎
信之 岩永
 
PPTX
C#や.NET Frameworkがやっていること
信之 岩永
 
PDF
Gitはじめの一歩
Ayana Yokota
 
PPTX
論文に関する基礎知識2016
Mai Otsuki
 
PDF
機械学習によるデータ分析 実践編
Ryota Kamoshida
 
PDF
データベース技術の羅針盤
Yoshinori Matsunobu
 
5分で分かるgitのrefspec
ikdysfm
 
Jenkins+Gitによる検証済みマージ(30分版)
Kohsuke Kawaguchi
 
GitHub入門 手順編
hideaki honda
 
やはりお前らのiOS7対応は間違っている
今城 善矩
 
査読の仕組みと論文投稿上の対策
Takayuki Itoh
 
HTML5ハイブリッド アプリ開発の実践〜開発現場ですぐに活かせるコツを伝授〜
Monaca
 
Xcodeを便利に使って爆速開発する #yxcm
Hiramatsu Ryosuke
 
iOS アプリのメンテナンス性を高めるための基本的な考え方
kakegawa-atsushi
 
Chrome Developer Toolsを使いこなそう!
yoshikawa_t
 
はやわかりHTML5ハイブリッドアプリ開発事情
Monaca
 
ネイティブとHTML5を スマートに連携させる設計と 実装のノウハウについて
Kazuaki Hidaka
 
数式を綺麗にプログラミングするコツ #spro2013
Shuyo Nakatani
 
pythonでオフィス快適化計画
Kazufumi Ohkawa
 
ソフトウェア設計のすすめ
Yoshimura Soichiro
 
非同期処理の基礎
信之 岩永
 
C#や.NET Frameworkがやっていること
信之 岩永
 
Gitはじめの一歩
Ayana Yokota
 
論文に関する基礎知識2016
Mai Otsuki
 
機械学習によるデータ分析 実践編
Ryota Kamoshida
 
データベース技術の羅針盤
Yoshinori Matsunobu
 
Ad

Similar to JavaScriptの落とし穴 (20)

PPT
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
Kazunori Tatsuki
 
PDF
Javascripでオブジェクト指向
1000 VICKY
 
PDF
JavaScript入門
Ryo Maruyama
 
PDF
JSクラス定義
Wataru Nakaseko
 
PDF
Effective JavaScript Ch.1
Teppei Sato
 
PDF
Kanazawa.js.Next
dynamis
 
PDF
ちょっと詳しくJavaScript 第3回【prototype】
株式会社ランチェスター
 
PDF
JavaScriptおよびXPages Vote技術解説
賢次 海老原
 
PDF
Web技術勉強会 20110514
龍一 田中
 
PPTX
Javascriptのデザインパターン【勉強会資料】
株式会社キャッチアップ
 
PDF
traceur-compilerで ECMAScript6を体験
Toshio Ehara
 
PDF
TypeScript と Visual Studio Code
Akira Inoue
 
PDF
JavaScript/CSS 2015 Autumn
Koji Ishimoto
 
PDF
ECMAScript 6 Features(PDF 版)
taskie
 
PDF
Web技術勉強会 20110723
龍一 田中
 
PDF
これからのJavaScriptー関数型プログラミングとECMAScript6
TanUkkii
 
PPTX
大人のお型付け
Nobuhisa Koizumi
 
PDF
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Masahiro Wakame
 
PDF
ちょっと詳しくJavaScript 特別編【悪霊の神々】
株式会社ランチェスター
 
PDF
大(中)規模Java script開発について
Yuki Tanaka
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
Kazunori Tatsuki
 
Javascripでオブジェクト指向
1000 VICKY
 
JavaScript入門
Ryo Maruyama
 
JSクラス定義
Wataru Nakaseko
 
Effective JavaScript Ch.1
Teppei Sato
 
Kanazawa.js.Next
dynamis
 
ちょっと詳しくJavaScript 第3回【prototype】
株式会社ランチェスター
 
JavaScriptおよびXPages Vote技術解説
賢次 海老原
 
Web技術勉強会 20110514
龍一 田中
 
Javascriptのデザインパターン【勉強会資料】
株式会社キャッチアップ
 
traceur-compilerで ECMAScript6を体験
Toshio Ehara
 
TypeScript と Visual Studio Code
Akira Inoue
 
JavaScript/CSS 2015 Autumn
Koji Ishimoto
 
ECMAScript 6 Features(PDF 版)
taskie
 
Web技術勉強会 20110723
龍一 田中
 
これからのJavaScriptー関数型プログラミングとECMAScript6
TanUkkii
 
大人のお型付け
Nobuhisa Koizumi
 
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Masahiro Wakame
 
ちょっと詳しくJavaScript 特別編【悪霊の神々】
株式会社ランチェスター
 
大(中)規模Java script開発について
Yuki Tanaka
 
Ad

JavaScriptの落とし穴