Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JavaScriptの落とし穴

33,963 views

Published on

社内勉強会用の発表資料

Published in: Education
  • Be the first to comment

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. ご清聴ありがとうございました

×