JavaScriptの落とし穴

32,191 views
32,009 views

Published on

社内勉強会用の発表資料

Published in: Education
0 Comments
130 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
32,191
On SlideShare
0
From Embeds
0
Number of Embeds
879
Actions
Shares
0
Downloads
182
Comments
0
Likes
130
Embeds 0
No embeds

No notes for slide

JavaScriptの落とし穴

  1. 1. 2013/4/27 @ HC社内勉強会JavaScriptの落とし穴
  2. 2. 今日話すこと普通のOOPL経験者から見たコアJSのハマりどころ→ 基礎的な話→ イディオムの理解
  3. 3. 基礎編
  4. 4. JSのオブジェクトは連想配列みたいなもの1 // 空のオブジェクトを作成2 var dog = {};34 // プロパティをひとつ追加5 dog.name = "Pochi";67 // ブラケットでもアクセスできる8 dog[breed] = "Shih Tzu";910 // 関数をひとつ追加 -> メソッド11 dog.getBreed = function () {12 return this.breed;13 }
  5. 5. JSのオブジェクトは連想配列みたいなもの1 // 同じものをオブジェクトリテラルで表記2 var dog = {3 name: "Pochi",4 breed: "Shih Tzu",5 getBreed: function () {6 return this.breed;7 }8 };
  6. 6. クラスっぽいものとコンストラクタ関数1 // Stringはコンストラクタなのか?2 var str1 = new String(123);3 console.log(str1); // "123"45 // 関数? それともキャスト???6 var str2 = String(456);7 console.log(str2); // "456"
  7. 7. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  8. 8. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  9. 9. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  10. 10. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  11. 11. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  12. 12. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  13. 13. クラスっぽいものとコンストラクタ関数1 // クラスっぽいものを作るコンストラクタ2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // new をつけて呼び出す10 var adam = new Person("Adam");11 console.log(adam.say()); //"I am Adam"1213 // new をつけずに呼び出す14 var eve = Person("Eve");15 console.log(eve); //undefined!オブジェクトthisname : Adamsay : {...}adam
  14. 14. 関数のnew呼び出し明示的な指定呼び出しメソッド呼び出しそれ以外(グローバル)第一の鬼門、this
  15. 15. 明示的な指定呼び出し1 var prop = "gProp";2 var obj = {prop : "rProp"};34 var func = function (str) {5 console.log(this.prop + "::" + str);6 };78 func("normal"); // gProp::normal9 func.call(obj, "call"); // rProp::call10 func.apply(obj, ["apply"]); // rProp::apply
  16. 16. メソッド呼び出し1 var prop = "gProp";2 var obj = {3 prop : "rProp",4 func : function (str) {5 console.log(this.prop + "::" + str);6 }7 };89 obj.func("dot"); // rProp::dot10 obj[func]("bracket"); // rProp::bracket1112 var func2 = obj.func;13 func2("func2"); // gProp::func2
  17. 17. 第二の鬼門、暗黙の型変換1 100 - 1; // 992 100 - 1; // 993 100 + 1; // “1001”4 1 + 100; // “1100”5 typeof +100; // “number”67 // null,undefined,0,-0,NaN,"" はfalse扱い8 var b = new Boolean(false);9 if (b) {/* 実行される */}1011 var n = new Number(0);12 if (n) {/* 実行される */}
  18. 18. 第二の鬼門、暗黙の型変換1 function Person (name, age) {2 this.name = name || "Guest";3 this.age = age || 20;4 }56 // {name:"Guest", age:20}7 var p1 = new Person();89 // {name:"Baby", age:20} になってしまう10 var p2 = new Person("Baby", 0);
  19. 19. 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" == { // truetoString:function(){return "Str"}};13 {} == true; // false. ★その他 if ({}) {実行される}14 {} == false; // false.同値演算子 == と ===
  20. 20. 問題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");というコードがあるとき、
  21. 21. 問題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");というコードがあるとき、
  22. 22. 問題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");というコードがあるとき、
  23. 23. 問題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");というコードがあるとき、
  24. 24. 問題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");というコードがあるとき、
  25. 25. 問題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");というコードがあるとき、
  26. 26. FunctionChildprototype:Object無名constructor:Objectc1name: Cain1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");3 c1.constructor === Child; // true
  27. 27. FunctionChildprototype:Object無名constructor:Objectc1name: Cain1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");3 c1.constructor === Child; // true
  28. 28. FunctionChildprototype:Object無名constructor:Objectc1name: Cain1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");3 c1.constructor === Child; // true
  29. 29. FunctionChildprototype:Object無名constructor:Objectc1name: Cain1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");3 c1.constructor === Child; // true
  30. 30. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  31. 31. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  32. 32. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  33. 33. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  34. 34. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  35. 35. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  36. 36. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  37. 37. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  38. 38. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  39. 39. 1 var Child = function (name) {this.name = name;};2 var Parent = function (name) {this.name = name;};3 Child.prototype = new Parent("Adam");45 var c1 = new Child("Cain");6 Parent.prototype.getName = function () {return this.name;};7 c1.getName(); // “Cain”.ChildChildprotoParentParentprotoAdamCainメソッドgetNameObjectObjectprototoStringvalueOfetc...
  40. 40. メソッドはprototypeに1 // クラスっぽいものを作るコンストラクタ(修正前)2 var Person = function (name) {3 this.name = name;4 this.say = function () {5 return "I am " + this.name;6 };7 };89 // 修正後10 var Person2 = function (name) {11 this.name = name;12 };1314 Person2.prototype.say = function () {15 return "I am " + this.name;16 };
  41. 41. 暗黙じゃない環境もある1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");34 c1.__proto__ === Child.prototype; // 環境依存でtrueFunctionChildprototype:Object無名constructor:Objectc1name: CainObjectc1__proto__:name: Cain
  42. 42. 暗黙じゃない環境もある1 var Child = function (name) {this.name = name;};2 var c1 = new Child("Cain");34 c1.__proto__ === Child.prototype; // 環境依存でtrueFunctionChildprototype:Object無名constructor:Objectc1name: CainObjectc1__proto__:name: Cain
  43. 43. ChildAdamCainParentParentprotoあくまでオブジェクトのチェーンであるEveAbelSeth
  44. 44. ChildAdamCainParentParentprotoあくまでオブジェクトのチェーンであるEveAbelSeth
  45. 45. ChildAdamCainParentParentprotoあくまでオブジェクトのチェーンであるEveAbelSeth
  46. 46. ChildAdamCainParentParentprotoあくまでオブジェクトのチェーンであるEveAbelSeth
  47. 47. ChildAdamCainParentParentprotoあくまでオブジェクトのチェーンであるEveAbelSeth
  48. 48. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  49. 49. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  50. 50. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  51. 51. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  52. 52. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  53. 53. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  54. 54. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  55. 55. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  56. 56. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  57. 57. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  58. 58. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  59. 59. ×Childprototype無名constructorc1__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__は同じオブジェクトを参照する。○か×か?(ただし環境に依る)無名constructorFunctionprototypecall()apply()etc...問題4:ChildのプロトタイプオブジェクトはChild.prototypeが参照するオブジェクトである。○か×か?
  60. 60. 継承は手段のひとつコードの再利用こそが目的継承にはいくつも方法があるObject.create();委譲、ミックスイン
  61. 61. 最後の鬼門、スコープチェーン
  62. 62. 1 var temp1 = "grobal1";2 var temp2 = "grobal2"3 console.log(temp1); // "grobal1"4 console.log(temp2); // "grobal2"56 func();7 function func () {8 console.log(temp2); // "grobal2"9 var temp1 = "local";10 console.log(temp1); // "local"1112 if (true) {13 console.log(temp1); // "local"14 var temp1 = "if";15 console.log(temp1); // "if"16 }17 console.log(temp1); // "if"18 }1920 console.log(temp1); // "grobal1"
  63. 63. 1 var temp1 = "grobal1";2 var temp2 = "grobal2"3 console.log(temp1); // "grobal1"4 console.log(temp2); // "grobal2"56 func();7 function func () {8 console.log(temp1); // undefined9 console.log(temp2); // "grobal2"10 var temp1 = "local";11 console.log(temp1); // "local"12 }1314 console.log(temp1); // "grobal1"15 console.log(temp2); // "grobal2"変数の巻き上げ
  64. 64. 1 var func1 = function () {2 console.log(arg); // undefined3 var arg = "local";4 };56 var func2 = function () {7 var arg = undefined;8 console.log(arg); // undefined9 arg = "local";10 };変数の巻き上げ
  65. 65. 1 func("one"); // "one"2 func(); // undefined3 func("one", "two", "three"); // "one"45 function func (arg1) {6 console.log(arg1);7 }もう少し詳しい理解
  66. 66. 1 func("one"); // "one"2 func(); // undefined3 func("one", "two", "three"); // "one two three"45 function func (arg1) {6 console.log(arg1);78 for (i = 1; i < arguments.length; i++) {9 console.log(arguments[i]);10 }11 }もう少し詳しい理解
  67. 67. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  68. 68. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  69. 69. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  70. 70. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  71. 71. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  72. 72. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  73. 73. globalオブジェクトf : function{...}x : xxx1 var x = "xxx";2 f(100, 200, 300);34 function f(a1) {5 var y = "yyy";6 g(200);78 function g(a1) {9 console.log(z); // undefined10 console.log(y); // "yyy"11 console.log(x); // "xxx"12 var z = "zzz";13 }14 }CallオブジェクトfのCallオブジェクトarguments : [...]a1 : arguments[0]y : undefinedg : function{...}fのCallオブジェクトarguments : [...]a1 : arguments[0]y : yyyg : function{...}gのCallオブジェクトarguments : [...]a1 : arguments[0]z : undefined
  74. 74. レキシカル(字句的)スコープ1 var x = 100;2 var y = 200;34 f();56 function f () {7 var y = 20;8 g();9 }1011 function g () {12 var z = 3;13 console.log(x); // 10014 console.log(y); // ???15 console.log(z); // 316 }globalオブジェクトプロパティは省略fのCallオブジェクトプロパティは省略gのCallオブジェクトプロパティは省略関数fのスコープチェーン↓関数gのスコープチェーン↓
  75. 75. レキシカル(字句的)スコープ1 var x = 100;2 var y = 200;34 f();56 function f () {7 var y = 20;8 g();9 }1011 function g () {12 var z = 3;13 console.log(x); // 10014 console.log(y); // ???15 console.log(z); // 316 }globalオブジェクトプロパティは省略fのCallオブジェクトプロパティは省略gのCallオブジェクトプロパティは省略関数fのスコープチェーン↓関数gのスコープチェーン↓
  76. 76. レキシカル(字句的)スコープ1 var x = 100;2 var y = 200;34 f();56 function f () {7 var y = 20;8 g();9 }1011 function g () {12 var z = 3;13 console.log(x); // 10014 console.log(y); // ???15 console.log(z); // 316 }globalオブジェクトプロパティは省略fのCallオブジェクトプロパティは省略gのCallオブジェクトプロパティは省略関数fのスコープチェーン↓関数gのスコープチェーン↓
  77. 77. レキシカル(字句的)スコープ1 var x = 100;2 var y = 200;34 f();56 function f () {7 var y = 20;8 g();9 }1011 function g () {12 var z = 3;13 console.log(x); // 10014 console.log(y); // ???15 console.log(z); // 316 }globalオブジェクトプロパティは省略fのCallオブジェクトプロパティは省略gのCallオブジェクトプロパティは省略関数fのスコープチェーン↓関数gのスコープチェーン↓
  78. 78. スコープチェーンまとめスコープは2種類存在する→ letってのもあるけど割愛変数の巻き上げに注意する関数呼び出しでCallオブジェクトが生成される関数のスコープチェーンは関数の定義位置で決まる
  79. 79. ちょっとだけイディオム編
  80. 80. JSには以下の機能を実装するための構文がない名前空間モジュール、パッケージアクセス修飾子(private)
  81. 81. 即時関数パターン1 (function () {23 var days = [日,月,火,水,木,金,土];4 var day = new Date();5 console.log(days[day.getDay()] + , + day.getDate());67 })(); // "土,27"1 var func = function () { // 関数の宣言2 /* 関数の中身 */3 };45 func(); // 関数の実行
  82. 82. クロージャクロージャ(クロージャー、closure、閉包)はプログラミング言語における関数オブジェクトの一種。いくつかの言語ではラムダ式 (Lambda Expression) や無名関数 (Anonymous function) で実現している。引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。関数とそれを評価する環境のペアであるともいえる。
  83. 83. クロージャクロージャ(クロージャー、closure、閉包)はプログラミング言語における関数オブジェクトの一種。いくつかの言語ではラムダ式 (Lambda Expression) や無名関数 (Anonymous function) で実現している。引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。関数とそれを評価する環境のペアであるともいえる。
  84. 84. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  85. 85. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  86. 86. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  87. 87. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  88. 88. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  89. 89. 1 var makeFunc = function (base) {2 var step = 10;3 var count = 0;45 return function (arg) {6 var result7 = base + step * count + arg;8 count++;9 return result;10 }11 }1213 var c1 = makeFunc(500);14 console.log(c1(3)); // 50315 console.log(c1(6)); // 51616 console.log(c1(9)); // 529globalオブジェクトプロパティは省略makeFuncのCObase : 500step : 10count : 0c1のCOまだ生成されてない!c1のCO 一回目arg : 3makeFuncのCObase : 500step : 10count : 1c1のCO 二回目arg : 6
  90. 90. privateの実現1 function Animal(arg) {2 // 以下、プライベート3 var name = arg;45 // 以下、パブリック6 this.getName = function () {7 return name;8 };9 }1011 var dog = new Animal("dog");1213 console.log(dog.name); // undefined14 console.log(dog.getName()); // "dog"
  91. 91. Callオブジェクトが分かれば大体のイディオムは分かる即時関数パターン→ 一時的な変数をCallオブジェクトに閉じ込めるクロージャ→ 関数定義時の環境(状態)をSCに閉じ込めるprivateメンバ→ 隠蔽したい変数をCallオブジェクトに閉じ込める
  92. 92. 名前空間、モジュール等は以下の書籍で
  93. 93. おまけ
  94. 94. その他、良さげな理由静的型付け + 型推論ECMAScript6準拠IDEとの連携開発が活発
  95. 95. というわけで、TypeScriptやろうぜ!
  96. 96. ご清聴ありがとうございました

×