Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Advanced JavaScript

Advanced JavaScript

Learning the JavaScript concept you may not know

Avatar for Eric Shangkuan

Eric Shangkuan

April 16, 2010
Tweet

More Decks by Eric Shangkuan

Other Decks in Programming

Transcript

  1. Agenda • Development Tools (testing & debugging) • Types &

    Functions ◦ Scope, Context, Closure • Prototype-Oriented Programming • DOM Scripting • Efficient Practices • A Glance of HTML5
  2. Development Tools • Firefox http://getfirefox.com/ • Firebug http://getfirebug.com/ • Chrome

    + (builtin devtools) http://www.chromium.org/getting-involved/dev-channel
  3. Firebug Console • Debugging your JavaScript code. ◦ Use console

    object in your JavaScript code. ◦ Interactive in the console tab.
  4. The console Usage <script type="text/javascript"> var elem = document.getElementById('foo'); //

    check if the elem is correct console.log(elem); .... for (var i in objs) { console.log("Key: %s -> %o", i, objs[i]); } </script>
  5. JavaScript Scope • Scope is kept within a functions, but

    not within blocks. • What doest the following codes output? var a = 1; if (true) { var a = 2; } alert(a); function foo() { var a = 3; } foo(); alert(a);
  6. JavaScript Scope: var keyword • Use var to seperate the

    variable's scope. (ineffective in global/window scope) var a = 1; var c = 5; function foo() { var a = 3; b = 2; } foo(); alert(a); alert(window.b); alert(window.c);
  7. JavaScript Scope: Example • What happened in this code? var

    a = 1; function foo() { alert(a); var a = 100; .... } foo(); document.write('a: ' + a);
  8. JavaScript Types • Use typeof function to check the type.

    typeof('abcd') --> 'string' typeof(123) --> 'number' typeof(false) --> 'boolean' • Primitive types: ◦ undefined ◦ string: "foo", "5678", "bar" ◦ number: 1234, 12, 34.5 ◦ boolean: true, false
  9. JavaScript Types (cont.) • Object types: ◦ null ◦ array:

    [1, 3, 4] ◦ object (or DOM element) { 'a': 'abcd', 'b': [1, 2], 'c': { ... }, .... } • Function type: ◦ function(a, b) { .... };
  10. JavaScript Types Samples var aNum = 123; var aStr =

    'foobar'; var aBool = true; var anArr = [1, 2, 'abc']; var aFunc = function(a, b) { return a + b; }; var anObj = {a: '123', b: aFunc, c: anArr}; Use typeof to check their types.
  11. The constructor Property • typeof vs. constructor: var a =

    123, b = 'foobar'; typeof(a) == 'number' typeof(b) == 'string' a.constructor == Number b.constructor == String • Array is an exception: var anArr = [1, 2, 3]; typeof(anArr) == 'object' anArr.constructor == Array
  12. typeof vs. constructor typeof constructor 1234 'number' Number 'a string'

    'string' String [1, 2, 'abc'] 'object' Array function() { ... } 'function' Function {a: 123, b: 'abcd'} 'object' Object true 'boolean' Boolean new User() 'object' User null 'object' (exception) undefined 'undefined' (exception)
  13. The NaN/Infinity value • NaN menas: Not a Number Infinity:

    as its name • What happened if your parse a string into an integer ? var a = 'abcd'; document.write(parseInt(a)); • Both NaN and Infinity are number type. (but they cannot be calculated) ◦ Use isNaN function
  14. The Falsy value • The falsy value is told as

    false in the boolean expressions. • 0, ''(empty string), undefined, null, NaN, and !(trusy value) are falsy. ◦ But they're NOT equivalent! (== will do type coercion Bad Part) ▪ '' == '0' // false ▪ 0 == '' // true ▪ 0 == '0' // true ▪ false == '0' // true ▪ false == null // false ▪ null == undefined // true ▪ ' \t\r\n' == 0 // true ◦ Use ===, !== to do compare with falsy values.
  15. Manipulate the Object Type • You may use . or

    [] operator to access the properties in an object instance. ◦ Use property string while using []. • How to check if a property is defined under an object? (useful on checking if the library is loaded) ◦ hasOwnProperty method (Use string as the argument) ◦ in operator (also the property string) ◦ check if it's undefined • Delete a property: delete operator.
  16. Object: Property Retrieval var obj = { a: '12345', b:

    ['abc', 12345, 'xyz'], c: { m: 1234 } }; console.log(obj.hasOwnProperty('d')); // false console.log(obj.a === undefined); console.log('a' in obj); console.log(obj['c'].m);
  17. Object: Property Enumeration var obj = { a: '12345', b:

    ['abc', 12345, 'xyz'], c: { m: 1234 } }; for (var key in obj) { console.log('[%s] %o', key, obj[key]); }
  18. Object: Property Deletion var obj = { a: '12345', b:

    ['abc', 12345, 'xyz'], c: { m: 1234 } }; delete obj.c; console.log(obj);
  19. Function • Function in JavaScript: ◦ as a sub-routine ◦

    as a prototype (described later) • Types of definition: ◦ As a variable var aFunc = function(a, b) { .... }; ◦ Normal definition: function aFunc(a, b) { .... } ◦ Anonymous function (function(a, b) { .... })(2, 3);
  20. Function Arguments • Magic variable in functions: arguments var aFunc

    = function() { for (var i = 0; i < arguments.length; ++i) { console.log(arguments[i]); .... } }; aFunc(); aFunc(1); aFunc(2, 3);
  21. Function Overloading • e.g., in jQuery, the ajax shortcut functions

    are almost defined as the following form: ◦ $.get(url, parmas, callback); ◦ $.get(url, callback); • How to use arguments to overload your function? (Hint: tell the types of the function arguments)
  22. Function Invokation var func = function(a, b) { ...... };

    • Directly invoke func('abcd', 234); • Use call method func.call(window, 'abcd', 234); • Use apply method func.apply(window, ['abcd', 234]);
  23. Function Invokation (call) var func = function(a, b) { console.log(this.c

    + a + b); }; var c = 5; var obj = { c: 'abcd' }; func(3, 4); func.call(window, 3, 4); func.call(obj, 3, 4);
  24. Context: Who is this? var obj = { val: 100,

    incre: function() { this.val += 1; }, decre: function() { this.val -= 1; } }; console.log( obj.val ); /* 100 */ obj.incre(); console.log( obj.val); /* 101 */
  25. Context Misuse var obj = { val: 100, init: function()

    { var btn = document.getElmentById('btn'); btn.addEventListener('click' , function(e){ this.val += 1; }, false); } }; (after the button has been clicked...) console.log(obj.val); // still 100 (WHY?)
  26. Preserved Context (closure) var obj = { val: 100, init:

    function() { var that = this; var btn = document.getElmentById('btn'); btn.addEventListener('click', function(e){ that.val += 1; }, false); } }; (after the button has been clicked...) console.log(obj.val); // 101
  27. Closure • The variables in parent function can be accessed

    in the inner function. (even the parent function has finished) • What happened by following codes? function delayAlert() { var x = 10; setTimeout(function() { alert(x); }, 1000); x = 1000; } delayAlert();
  28. Closure Sample: Partial Function var adderGenerator = function(summand) { return

    function(addend) { return summand + addend; } }; var adder4 = adderGenerator(4); console.log(adder4(5)); // 9 var adder10 = adderGenerator(10); console.log(adder10(5)); // 15
  29. Closure Sample: Preserving Scope (function(){ var x; var f =

    function() { /* DO SOMETHING */ }; .... Foo = ... /* expose to global */ })(); /* x is undefined here, but Foo is defined */
  30. Object Creation var aObj = new Object(); aObj.x = 123;

    aObj.y = function() { alert('this.x = ' + this.x); }; alert(aObj.x); aObj.y(); // or var aObj = { x: 123, y: function() { alert('this.x = ' + this.x); } };
  31. Define a Prototype var Person = function(name, age){ this._name =

    name; this._age = age; }; var peter = new Person('Peter', 20); console.log(peter._name); peter._age++; console.log(peter._age); // 21 var mary = new Person('Mary', 18); console.log(mary._age);
  32. Define a Prototype (cont.) var Person = function(name, age){ this._name

    = name; this._age = age; }; Person.prototype.getName = function() { return this._name; } Person.prototype.setName = function(name) { this._name = name; }; Person.prototype.anotherObj = new Object();
  33. The constructor Property • (Recall) We used it to tell

    the type of a instance. • The constructor property is a reference to the Object function that creates the instance's prototype. ◦ Not a string, but it can be modified. ◦ instanceof operator • If var peter = new Person('Peter', 20); what's peter.constructor's value?
  34. Dynamic Binding var peter = new Person('Peter', 5); var mary

    = new Person('Mary', 1); peter.toys = ['Car', 'Robots']; // (undefined) Oh! Poor Mary. console.log(mary.toys);
  35. Dynamic Binding (cont.) var peter = new Person('Peter', 5); var

    mary = new Person('Mary', 1); Person.prototype.toys = ['Car', 'Robots']; // Now, Mary has toys. console.log(mary.toys);
  36. Encapsulation: Private Member var MyClz = function(x, y) { this.x

    = x; this.y = y; var _thePrivateMethod = function() { // do something... }; _thePrivateMethod(); } var obj = new MyClz(3, 4); obj._thePrivateMethod(); // error
  37. Encapsulation: Static Member var MyClz = function(x, y) { this.x

    = x; this.y = y; } MyClz.TheStaticMethod = function() { // do something... }; var obj = new MyClz(3, 4); obj.TheStaticMethod(); // error MyClz.TheStaticMethod(); // ok
  38. Inheritance var Person = function(name) { this._name = name; };

    Person.prototype.getName = function() { return this._name; }; var User = function(name, password) { this._name = name; this._password = password; }; User.prototype = new Person(); User.prototype.constructor = User; User.prototype.getPassword = function() { return this._password; };
  39. Inheritance: extends function var extends = function(subClass, supClass) { subClass.prototype

    = new supClass(); subClass.prototype.constructor = subClass; }; var Person = function(){ .... }; Person.prototype = { .... }; var User = function() { .... }; extends(User, Person); ....
  40. Inheritance: object inheritance var person = { _name: 'Eric', getName:

    function() { return this._name; } }; var foo = function() {}; foo.prototype = person; var user = new foo(); user.setPassword = function(pwd) { this._password = pwd; };
  41. Inheritance: clone method var clone = function(fromObj) { var f

    = function() {}; f.prototype = fromObj; return new f(); }; var user = clone(person); var user_1 = clone(user); var user_2 = clone(user); ....
  42. Mix-in: Inject Methods // declare an Authorized class var Authorized

    = function() {}; Authorized.prototype = { post: function() { // do post } }; // Injects Authorized's methods into User class mixin(User, Authorized); var u = new User('eric', 'pass'); u.post(); // ok
  43. Mix-in: The mixin Method var mixin = function(recv, from) {

    for (var method in from.prototype) { if (!(method in recv.prototype)) { recv.prototype[method] = from.prototype[method]; } } };
  44. DOM Manipulations: Selector • You can select DOM elements by

    following selector: ◦ id: getElementById(id) ◦ name: getElementsByName(name) ◦ Tag name: getElementsByTagName(tagName) ◦ class name: (FF3, SF/Ch, Mobile) getElementsByClassName (className) ◦ • HTML5: document.querySelector(cssSelector)
  45. DOM Manip: Create Elements • Use createElement method to create

    a DOM element, and use appendChild to append it into the DOM tree: var dom = document.createElement('div'); dom.id = 'newCreated'; dom.innerHTML = '<h1>Hi!</h1>'; document.body.appendChild(dom); • How to implement a prependChild method?
  46. DOM Manip: Insert Elements • Use insertBefore method to insert

    the DOM element according to a reference element: var ref = document.getElementById('base'); var parent = ref.parentNode; parent.insertBefore(dom, ref); • How to implement an insertAfter method?
  47. DOM Manip: Remove Elements • Use removeChild method to remove

    the DOM element from to an element: var ref = document.getElementById('base'); var parent = ref.parentNode; parent.removeChild(ref); • How to implement an replaceWith method?
  48. DOM Event: Event Listener • Register the event handler on

    an element: ◦ onclick attribute ▪ <input type="button" onclick="alert('hey!')"> ▪ context is window and tight to HTML ◦ onclick method ▪ dom.onclick = function() { ... }; ▪ cannot add multiple handlers ◦ event handler ▪ addEventListener (attachEvent in IE) ▪ multiple handlers ▪ remove/detach handlers ▪ removeEventListener
  49. DOM Event: Event Listener var dom = document.getElementById('button'); var handler

    = function(evt) { evt = evt || window.event; .... }; if (dom.addEventListener) { dom.addEventListener('click', handler, false); } else { dom.attachEvent('onclick', handler); }
  50. DOM Event: Prevent Defaults • On <a> tag, the click

    event fires the location change (according to href attribute) ◦ Use preventDefault to prevent firing. ◦ The submit event in form element. aLink.addEventListener('click', function(evt){ // do something ... evt.preventDefault(); }, false);
  51. DOM Event: Propagation • Stop propagate the event to the

    next element aLink.addEventListener('click', function(evt){ // do something ... evt.stopPropagation(); }, false);
  52. Efficient JavaScript Tips • Using className instead of modifying style

    attributes of a DOM element. [bad] var foo = document.getElementById('foo'); foo.style.color = '#f00'; foo.style.fontWeight = 'bold'; [good] .highlight { color: #f00; font-weight: bold; } foo.className = 'highlight';
  53. Efficient JavaScript Tips (cont.) • Avoid redundant layout invalidation [bad:

    invalidate twice, reflow twice] foo.className = 'foo'; var fooWidth = foo.offsetWidth; bar.className = 'bar'; var barWidth = bar.offsetWidth; [good: invalidate twice, reflow ONCE] foo.className = 'foo'; bar.className = 'bar'; var fooWidth = foo.offsetWidth; var barWidth = bar.offsetWidth;
  54. Efficient JavaScript Tips (con'd) • Appending a newly-created DOM element

    after modifying its attributes. (avoid reflows) [bad] var foo = document.createElement('div'); document.body.appendChild(foo); foo.innerHTML = 'Hello, world'; foo.className = 'hello'; [good] var foo = document.createElement('div'); foo.innerHTML = 'Hello, world'; foo.className = 'hello'; document.body.appendChild(foo);
  55. Efficient JavaScript Tips • Using document fragment to create new

    contents. [bad] document.body.appendChild(createDivElement()); document.body.appendChild(createDivElement()); ... [good] var frag = document.createDocumentFragment(); frag.appendChild(createDivElement()); frag.appendChild(createDivElement()); .... document.body.appendChild(frag);
  56. Efficient JavaScript Tips • Using array join instead of directly

    concatenate strings. [bad] var a = 'Hel'; a += 'lo'; a += ', wor'; a += 'ld!'; [good] var buf = ['Hel']; buf.push('lo'); buf.push(', wor'); buf.push('ld!'); a = buf.join('');
  57. Efficient JavaScript Tips • Faster trim method: (use simple regular

    expression) [bad] str.replace(/^\s+|\s+$/g, ''); [better] str.replace(/^\s+/, '').replace(/\s+$/, ''); [much better] str = str.replace(/^\s+/, ''); for (i = str.length - 1; i >= 0; i--) { if (/\S/.test(str.charAt(i))) { str = str.substring(0, i + 1); break; } }
  58. HTML5: The Next-Gen of Web • HTML5 (still in draft)

    defines many features that make web applications powerful. • 2/3D graphics/games, offline apps, videos/audios.... on Web is possible today (w/o plugins) • Mobile web browsers can utilize the offline, geolocation, ... features to develop interesting apps. • http://whatwg.org/html5
  59. The Geolocation API • Help you construct a LBS web

    apps. ◦ Integrate with Google Maps API/Services // Tell if the browser support Geolocation API if ("geolocation" in navigator) { navigator.geolocation.getCurrentPosition( succCallback, errCallback, {enableHighAccuracy: true} // options ); } var succCallback = function(data) { var pos = data.coords; console.log(pos.latitude + ", " + pos.longitude); };
  60. The WebStorage API • Help you store key/value data in

    the client. ◦ 2 types of storage: local, session ◦ IE8 supports this API // Tell if the browser support WebStorage API if ("localStorage" in window) { var key = 'counter'; // or localStorage.counter or localStorage[key] var counter = localStorage.getItem(key); if (counter === null) { counter = 0; } else { counter++; } // or localStorage.counter = counter or localStorage[key] = counter localStorage.putItem(key, counter); }
  61. The WebDatabase API • Help you store any types of

    data in the client. // Tell if the browser support Web Database API if ("openDatabase" in window) { var db = openDatabase("mydb", "", "My Test Db", 1048576, function(db){ db.changeVersion('', '1.0', function(t){ t.executeSql('CREATE TABLE note (id, name)'); }); }); // execute sql db.transaction(function(t){ t.executeSql('INSERT INTO note(id, name) VALUES(?, ?)', ['1', 'test']); }); }
  62. References • JavaScript: The Good Parts (ISBN: 978-0-596-51774-8) ◦ 中文版:JavaScript

    優良部份 • The JavaScript Programming Language (videos) ◦ http://video.yahoo.com/watch/111593/1710507 • Pro JavaScript Techniques (ISBN: 978-1-59059-727-9) • Pro JavaScript Design Patterns (ISBN: 978-1-59059-908-2) • High Performance Web Sites • Even Faster Web Sites