04 Advanced Javascript
Upcoming SlideShare
Loading in...5
×
 

04 Advanced Javascript

on

  • 80 views

Examples and concept from John Resig's tutorial here: http://ejohn.org/apps/learn/.

Examples and concept from John Resig's tutorial here: http://ejohn.org/apps/learn/.

Statistics

Views

Total Views
80
Views on SlideShare
80
Embed Views
0

Actions

Likes
0
Downloads
1
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

04 Advanced Javascript 04 Advanced Javascript Presentation Transcript

  • Intro to jQuery Web Development 101 Lesson 03.01
  • jQuery is great
  • Advanced Javascript. Web Development 101 Lesson 03.01
  • OR What 80% of Javascript programmers don’t know about their own language.
  • // The .bind method from Prototype.js Function.prototype.bind = function() { var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function() { return fn.apply( object, args.concat( Array.prototype.slice.call(arguments) ) ); }; };
  • What ways can we define functions?
  • function funcA(){ return true; } var funcB = function(){ return true; }; window.funcC = function(){ return true; }; ! assert( funcA() && funcB() && funcC() );
  • var funcB = function(){ return true; }; window.funcC = function(){ return true; }; ! assert( funcA() && funcB() && funcC() ); ! function funcA(){ return true; }
  • function stealthCheck(){ assert( stealth() ); ! return stealth(); ! function stealth(){ return true; } } ! stealthCheck();
  • function factorial(n) { return n * (n > 1 ? factorial(n - 1) : 1); } ! factorial(10);
  • var factorial = function f(n) { return n * (n > 1 ? f(n - 1) : 1); } ! factorial(10); // Works f(10); // Undefined function
  • Is a function an object?
  • var obj = {}; var fn = function(){}; ! obj.prop = "some value"; fn.prop = "some value";
  • var factorial = function f(n) { f.cache = f.cache || {}; if (!f.cache[n]) { f.cache[n] = n * (n > 1 ? f(n - 1) : 1); } return f.cache[n]; } ! factorial(10); factorial(9); factorial(20);
  • How does `this` work?
  • var katana = { isSharp: true, use: function(){ this.isSharp = false; } }; ! katana.use(); katana.isSharp === false;
  • function katana(){ this.isSharp = true; } katana(); isSharp === true; ! ! var shuriken = { toss: function(){ this.isSharp = true; } }; shuriken.toss(); shuriken.isSharp === true;
  • How do I change `this`?
  • var object = {}; function fn(){ return this; } ! fn() === this === window; ! fn.call(object) === object;
  • var object = {a: ‘Jeremiah’, b: ‘Baruch’}; ! function getAttr(a){ return this[a]; } ! getAttr.call(object, ‘a’) === ‘Jeremiah’; ! getAttr.apply(object, [‘b’]) === ‘Baruch’;
  • Can I instantiate a function?
  • function Pioneer(){ this.name = "Pioneer"; } ! joe = Pioneer(); joe === undefined; ! joe = new Pioneer(); joe.name == "Pioneer";
  • function Pioneer(){ this.hasBibleStudy = false; ! this.preach = function() { this.hasBibleStudy = true; }; } ! jack = new Pioneer(); jill = new Pioneer(); ! jack.hasBibleStudy === false; jill.hasBibleStudy === false; ! jack.preach(); ! jack.hasBibleStudy === true; jill.hasBibleStudy === false;
  • function Pioneer(){ this.hasBibleStudy = false; ! this.preach = function() { this.hasBibleStudy = true; }; } ! jack = Pioneer(); jill = Pioneer(); ! jack.hasBibleStudy === false; // Fatal Type Error jill.hasBibleStudy === false; ! jack.preach(); ! jack.hasBibleStudy === true; jill.hasBibleStudy === false;
  • Can I build a function with variable number of arguments?
  • var object = {a: ‘Jeremiah’, b: ‘Baruch’}; ! function getAttr(a){ return this[a]; } ! getAttr.apply(object, [‘b’]) === ‘Baruch’;
  • var object = {a: ‘Jeremiah’, b: ‘Baruch’}; ! function getAttr() { var out = [], i; for (i = 0; i < arguments.length; i++) { out.push( this[ arguments[i] ] ); } return out; } ! getAttr.apply(object, [‘a’, ‘b’]) === [‘Jeremiah’, ‘Baruch’];
  • function smallest(array){ return Math.min.apply( Math, array ); } ! function largest(array){ return Math.max.apply( Math, array ); } ! assert(smallest([0, 1, 2, 3]) == 0); assert(largest([0, 1, 2, 3]) == 3);
  • function smallest() { return Math.min.apply( Math, arguments ); } ! function largest() { return Math.max.apply( Math, arguments ); } ! assert(smallest(0, 1, 2, 3) == 0); assert(largest(0, 1, 2, 3) == 3);
  • function highest(){ return arguments.sort(function(a, b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3;
  • function highest(){ return arguments.sort(function(a, b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3; // Fatal Error.
  • `arguments` isn’t actually an array
  • function highest() { var argArray = Array().slice.call(arguments); return argArray.sort(function(a, b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3;
  • How do Closures work?
  • var a = 5; ! function runMe(a) { assert( a == ___, "Check the value of a." ); ! function innerRun(){ assert( b == ___, "Check the value of b." ); assert( c == ___, "Check the value of c." ); } ! var b = 7; innerRun(); var c = 8; } ! runMe(6); ! for ( var d = 0; d < 3; d++ ) { setTimeout(function(){ assert( d == ___, "Check the value of d." ); }, 100); }
  • var a = 5; ! function runMe(a) { assert( a == 6, "Check the value of a." ); ! function innerRun(){ assert( b == 7, "Check the value of b." ); assert( c == undefined, "Check the value of c." ); } ! var b = 7; innerRun(); var c = 8; } ! runMe(6); ! for ( var d = 0; d < 3; d++ ) { setTimeout(function(){ assert( d == 3, "Check the value of d." ); }, 100); }
  • ! for ( var d = 0; d < 3; d++ ) { setTimeout(function(){ assert( d == 3, "Check the value of d." ); }, 100); }
  • for (var d = 0; d < 3; d++) { (function (d) { setTimeout(function () { console.log(d); }, 100); }(d)); }
  • Code smell: Don’t make closures inside a loop. Normally.
  • How do I make a class?
  • #!/usr/bin/env python ! class Pioneer(object): def __init__(self, name): self.name = name self.bibleStudies = 0 ! def preach(self): self.bibleStudies += 1 ! joe = Pioneer(“Joe”) joe.preach();
  • #!/usr/bin/env php ! class Pioneer { private name; private bibleStudies; ! public function __construct(name) { this.name = name; this.bibleStudies = 0; } ! public function preach() { this.bibleStudies++; } } ! joe = new Pioneer(“Joe”); joe->preach();
  • Write `Pioneer` in JS.
  • var Pioneer = function(name) { this.name = name; this.bibleStudies = 0; ! this.preach = function() { this.bibleStudies++; }; }; ! joe = new Pioneer(“Joe”); joe.preach();
  • var Pioneer = function(name) { this.name = name; this.bibleStudies = 0; }; ! Pioneer.prototype = {}; Pioneer.prototype.preach = function() { this.bibleStudies++; }; ! joe = new Pioneer(“Joe”); joe.preach();
  • Inheritance. Prototypal Inheritance.
  • var Pioneer = function (name) { this.name = name; this.bibleStudies = 0; }; ! Pioneer.prototype = {}; Pioneer.prototype.preach = function () { this.bibleStudies++; }; ! var SpecialPioneer = function(name) { this.name = name; this.bibleStudies = 0; }; ! SpecialPioneer.prototype = new Pioneer(); SpecialPioneer.prototype.preach = function () { this.bibleStudies += 5; }; ! var joe = new Pioneer("Joe"), jeremy = new SpecialPioneer('Jeremy'); ! joe.preach(); jeremy.preach();
  • Enforcing Function Context
  • var Button = { click: function(){ this.clicked = true; } }; ! var elem = document.createElement("li"); elem.innerHTML = "Click me!"; elem.onclick = Button.click; document.getElementById("results").appendChild(elem); ! elem.onclick(); ! Button.clicked === undefined; elem.clicked === true;
  • function bind(context, name){ return function() { return context[name].apply(context, arguments); }; } ! var Button = { click: function(){ this.clicked = true; } }; ! var elem = document.createElement("li"); elem.innerHTML = "Click me!"; elem.onclick = bind(Button, "click"); document.getElementById("results").appendChild(elem); ! elem.onclick(); ! Button.clicked === true; elem.clicked === undefined;
  • Function.prototype.bind = function(object) { var fn = this; return function(){ return fn.apply(object, arguments); }; }; ! var Button = { click: function(){ this.clicked = true; } }; ! var elem = document.createElement("li"); elem.innerHTML = "Click me!"; elem.onclick = Button.click.bind(Button); document.getElementById("results").appendChild(elem); ! elem.onclick(); ! Button.clicked === true;
  • Back to our original goal
  • // The .bind method from Prototype.js Function.prototype.bind = function() { var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function() { return fn.apply( object, args.concat( Array.prototype.slice.call(arguments) ) ); }; };
  • Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; }; ! var Button = { click: function(value) { this.clicked = value; } }; ! var elem = document.createElement("li"); elem.innerHTML = "Click me!"; elem.onclick = Button.click.bind(Button, “I was clicked!”); document.getElementById("results").appendChild(elem); ! elem.onclick(); ! Button.clicked === “I was clicked!”
  • Functions can be defined 3 ways Closures can be used to cache values for later, including execution scope. Functions are just objects that you can execute. Objects inherit from each other using prototypes. The `this` keyword is bound to function context Build in object prototypes can be extended. No classes, just objects. All of that works without including jQuery at all.
  • Moral of the story
  • Javascript is a great, although quirky, language. Prototypal inheritance works similarly, but not exactly like class inheritance. jQuery is a great library. You should use it for DOM and AJAX code. Reading API documentation will teach you jQuery. A good understanding of Javascript is harder to come by.
  • :rewind
  • var Pioneer = function (name) { this.name = name; this.bibleStudies = 0; }; ! Pioneer.prototype = {}; Pioneer.prototype.preach = function () { this.bibleStudies++; }; ! var SpecialPioneer = function(name) { this.name = name; this.bibleStudies = 0; }; ! SpecialPioneer.prototype = new Pioneer(); SpecialPioneer.prototype.preach = function () { this.bibleStudies += 5; }; ! var joe = new Pioneer("Joe"), jeremy = new SpecialPioneer('Jeremy'); ! joe.preach(); jeremy.preach();
  • Let’s make inheritance better.
  • var Person = Class.extend({ init: function (isDancing) { this.dancing = isDancing; }, dance: function () { return this.dancing; } }); ! var Ninja = Person.extend({ init: function () { this._super(false); }, dance: function () { // Call the inherited version of dance() return this._super(); }, swingSword: function () { return true; } }); ! var p = new Person(true); p.dance(); // => true ! var n = new Ninja(); n.dance(); // => false n.swingSword(); // => true ! // Should all be true p instanceof Person && p instanceof Class && n instanceof Ninja && n instanceof Person && n instanceof Class