認識 JavaScript : 與其它程式語言的異同

認識 JavaScript : 與其它程式語言的異同

2011 微軟開發者日

7067c01e5e98f8b8211343054a908076?s=128

Ping-Yen Tsai

June 21, 2011
Tweet

Transcript

  1. 認識 JavaScript : 與其它程式語⾔言的異同 Vexed 蔡秉諺

  2. 個⼈人簡歷 • 中正⼤大學電⼦子計算機中⼼心 • 中正資⼯工 GAIS Lab • 新典資訊 •

    中華電信數據通信分公司網際內容處三科
  3. Why me? • HTML5 • Core JavaScript Client-side JavaScript Core

    JavaScript Server-side JavaScript Core JavaScript JScript .NET Core JavaScript
  4. Literal 實字 var o1 = new Object(); var o2 =

    new Object(); o2.p = 1; o2.q = 2; var a1 = new Array(); var a2 = new Array(); a2[0] = 1; a2[1] = 2; var o1 = {}; var o2 = { p : 1, q : 2 }; var a1 = []; var a2 = [1, 2]; ← 意義相同 → JSON ?
  5. Regular Expression Literal var r1 = new RegExp('JavaScript'); var r2

    = new RegExp('JavaScript', 'gi'); var r1 = /JavaScript/; var r2 = /JavaScript/gi; ↑ 意義相同 ↓
  6. JavaScript is • weak typing ⾃自動轉型 • dynamic typing •

    執⾏行期間增改刪屬性 var o = {}; o.p = 1 + '2'; // '12' o.p = function(){ alert('f'); } o.p(); // f delete o.p;
  7. Data Type • Primitive Type – number (值 float, 沒有型態

    int) – string (沒有型態 char) – boolean – null – undefined • Object – Array – Function … string -> String number -> Number boolean -> Boolean var s = 'ABCDE'; alert(s.substr(1, 2)); // BC weak typing ⾃自動轉型
  8. Operator • ⼤大致和其他語⾔言相同 • weak typing == != 轉型後⽐比對 ===

    !== 型態也需相同⽐比對 • && || 不是回傳 true false 回傳確⽴立結果時的運算元 var a = 1 && 's'; // 's' var b = null && 1; // null var c = 1 || 's'; // 1 var d = null || 0; // 0
  9. 物件屬性存取⽅方式 • . 和 [] o.p ←意義相同→ o['p'] • 屬性名稱可以包含

    任意字元 o['~!@#$%^&*(.'] var s = 'p'; var a = o[s]; var b = eval('o.' + s); var o = { '~!@#$%^&*.' : 1 }; Object Literal
  10. 物件好像 C# Dictionary, Java Map var o = {}; var

    key = 'k', value = 'v'; o[key] = value; if(o[key]) alert(o[key]); // v for(var i in o) { alert(i); // k alert(o[i]); // v } delete o[key];
  11. Function 是物件 var f1 = new Function('x', 'y', 'return x

    + y'); var a = f2(1, 1); // js error, f2 is not a function var f2 = function(x, y) { return x + y; } var b = f2(1, 1); // 2 var c = f3(1, 1); // 2 function f3(x, y) { return x + y; }
  12. Function 參數個數不受限 f(1) // 1, undefined, undefined f(1, 2, 3,

    4) // 1, 2, 3 function f(a, b, c) { alert(a); alert(b); alert(c); }
  13. arguments 存取參數 f(1, 2, 3, 4); function f() { var

    x = arguments.length; // 4 var y = arguments[2]; // 3 }
  14. 給予 Function 參數初始值 function f(a, b, c) { a =

    a || 1; b = b || 2; c = c || 3; }
  15. Anonymous function 匿名函式 var a = [1, 3, 2, 5,

    4]; function compare(a, b){ return a - b; } a.sort(compare); alert(a); // 1,2,3,4,5 var a = [1, 3, 2, 5, 4]; a.sort(function(a, b) { return a - b; }); alert(a); // 1,2,3,4,5
  16. self executing anonymous function
 ⾃自⼰己執⾏行的匿名函式 (function() { /* 乾淨的變數空間 */

    var a = 1; })(); alert(a); // js error, a is not defined
  17. 匿名函式也可以遞迴 var m = (function(n) { // factorial if(n <=

    1) return 1; return n * arguments.callee(n - 1); })(3); oDiv.addEventListener('click', function() { oDiv.removeEventListener('click', arguments.callee); // ... }); Event 只執⾏行⼀一次
  18. 函式中宣告變數沒寫 var 會是全域變數 (function() { var a = 1; })();

    alert(a); // js error, a is not defined (function() { a = 1; })(); alert(a); // 1
  19. 函式中的 this function f() { alert(this.p); } var a =

    { p : 1, m : f }, b = { p : 2, m : f }; a.m(); // 1 b.m(); // 2 f(); // undefined
  20. ⽤用 call, apply 指定 this function f() { alert(this.p); }

    var a = { p : 1, m : f }, b = { p : 2, m : f }; a.m.call(b); // 2 f.call(b); // 2 a.m.call(b, 3, 4); a.m.apply(b, [3, 4]); function g() { a.m.apply(b, arguments); }
  21. 沒指定, this 就是 Global Object function f() { alert(this.p); }

    f(); // undefined var p = 1; f(); // 1 Global 變數 就是 Global Object 的屬性
  22. 函式裡⾯面可以再寫函式 function f() { g(); // 1 function g() {

    alert(1); } } g(); // js error: g is not defined 裡⾯面的函式 global 看不⾒見
  23. 裡⾯面的函式可以存取外⾯面函式的變數 function f() { var a = 1; g(); alert(a);

    // 2 g(); alert(a); // 3 function g() { ++a; } }
  24. 裡⾯面的函式宣告和外⾯面函式⼀一樣的變數
 裡⾯面⽤用裡⾯面的 外⾯面⽤用外⾯面的 function f() { var a = 1;

    g(); alert(a); // 1 function g() { alert(a); // undefined var a = 2; alert(a); // 2 } }
  25. Closure = 函式 + 外⾯面的變數 function f() { var a

    = 1; function g() { ++a; } } var h = f(); function f() { var a = 1; function g() { ++a; } return g; }
  26. Closure 匿名函式化 var h = (function() { var a =

    1; return function() { ++a; } })(); var h = (function() { var count = 0; return function() { ++count; // 計算 h 的執⾏行次數 } })();
  27. Scope chain var a = 1; function f() { var

    b = 2; g(); function g() { var c = 3; h(); function h() { var d = 4; alert(d); // 4 alert(c); // 3 alert(b); // 2 alert(a); // 1 } } } 裡⾯面的函式存取外⾯面函式的變數
  28. Constructor function Cat(name) { this.name = name; } var cat1

    = new Cat('kitty'), cat2 = new Cat('lucky'); alert(cat1.name); // 'kitty' alert(cat2.name); // 'lucky' alert(cat1 instanceof Cat); // true alert(cat1.constructor); // function Cat(name) { … }
  29. 函式就是 Constructor function Cat(name) { this.name = name; } var

    cat1 = new Cat('kitty'); 關鍵在有沒有 new
  30. 記得寫 new function Cat(name) { this.name = name; } var

    cat1 = Cat('kitty'); alert(cat1); // undefined alert(name); // kitty /* 沒有錯誤 */
  31. Prototype • Constructor 的⼀一個屬性 預設是空物件 {} • instance 沒有的屬性會到 Constructor.prototype

    找 • 所有這個 Constructor new 出來的 instance 共⽤用 ! ?
  32. Prototype範例 function Cat(name) { this.name = name; } Cat.prototype.meow =

    function() { alert('meow'); } var cat1 = new Cat('kitty'), cat2 = new Cat('lucky'); cat1.meow(); // meow cat2.meow(); // meow cat1.meow = function() { alert('bark'); } cat1.meow(); // bark cat2.meow(); // meow
  33. hasOwnProperty
 檢查是⾃自⼰己的屬性 還是 prototype 的 function Cat(name) { this.name =

    name; } Cat.prototype.meow = function() { alert('meow'); } var cat1 = new Cat('kitty'); alert(cat1.hasOwnProperty(name)); // true alert(cat1.hasOwnProperty(meow)); // false
  34. constructor 屬性是在 prototype 上 function Cat(name) { this.name = name;

    } var cat1 = new Cat('kitty'); alert(cat1.constructor); // function Cat(name) { … } alert(cat1.hasOwnProperty('constructor')); // false alert(Cat.prototype.constructor); // function Cat(name) { … }
  35. 把 prototype 覆蓋掉 function Cat(name) { this.name = name; }

    Cat.prototype = { age : 1, gender : 'female' } var cat1 = new Cat('kitty'); alert(cat1.constructor); // function Object() { [native code] } alert(Cat.prototype.constructor); // function Object() { [native code] }
  36. 覆蓋 prototype 多寫屬性 constructor function Cat(name) { this.name = name;

    } Cat.prototype = { age : 1, gender : 'female', constructor : Cat } var cat1 = new Cat('kitty'); alert(cat1.constructor); // function Cat() { [native code] }
  37. 讓 prototype 是另⼀一個物件 instance function Animal() { } Animal.prototype.energy =

    100; function Cat(name) { this.name = name; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat('kitty'); alert(cat1.energy); // 100 cat1 ↓ Cat.prototype ↓ Animal.prototype ↓ Object.prototype Object.prototype.everyone = 'Yes'; alert(cat1.everyone); // Yes Prototype chain alert(cat1 instanceof Cat); // true alert(cat1 instanceof Animal); // true alert(cat1 instanceof Object); // true alert(cat1 instanceof Array); // false
  38. instance 參照的 prototype
 在 new 時就綁定 function Cat(name) { this.name

    = name; } Cat.prototype.age = 10; var cat1 = new Cat('kitty'); alert(cat1.age); // 10 alert(cat1 instanceof Cat); // true Cat.prototype = { age : 20, constructor : Cat }; alert(cat1.age); // 10 var cat2 = new Cat('lucky'); alert(cat1 instanceof Cat); // false alert(cat2 instanceof Cat); // true
  39. Q & A