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

Advanced JavaScript

Advanced JavaScript

Learning the JavaScript concept you may not know

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