KEMBAR78
04 Advanced Javascript | PDF
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

04 Advanced Javascript

  • 1.
    Intro to jQuery WebDevelopment 101 Lesson 03.01
  • 2.
  • 4.
  • 5.
    OR What 80% ofJavascript programmers don’t know about their own language.
  • 6.
    // The .bindmethod 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) ) ); }; };
  • 7.
    What ways canwe define functions?
  • 8.
    function funcA(){ returntrue; } var funcB = function(){ return true; }; window.funcC = function(){ return true; }; ! assert( funcA() && funcB() && funcC() );
  • 9.
    var funcB =function(){ return true; }; window.funcC = function(){ return true; }; ! assert( funcA() && funcB() && funcC() ); ! function funcA(){ return true; }
  • 10.
    function stealthCheck(){ assert( stealth()); ! return stealth(); ! function stealth(){ return true; } } ! stealthCheck();
  • 11.
    function factorial(n) { returnn * (n > 1 ? factorial(n - 1) : 1); } ! factorial(10);
  • 12.
    var factorial =function f(n) { return n * (n > 1 ? f(n - 1) : 1); } ! factorial(10); // Works f(10); // Undefined function
  • 13.
    Is a functionan object?
  • 14.
    var obj ={}; var fn = function(){}; ! obj.prop = "some value"; fn.prop = "some value";
  • 15.
    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);
  • 16.
  • 17.
    var katana ={ isSharp: true, use: function(){ this.isSharp = false; } }; ! katana.use(); katana.isSharp === false;
  • 18.
    function katana(){ this.isSharp =true; } katana(); isSharp === true; ! ! var shuriken = { toss: function(){ this.isSharp = true; } }; shuriken.toss(); shuriken.isSharp === true;
  • 19.
    How do Ichange `this`?
  • 20.
    var object ={}; function fn(){ return this; } ! fn() === this === window; ! fn.call(object) === object;
  • 21.
    var object ={a: ‘Jeremiah’, b: ‘Baruch’}; ! function getAttr(a){ return this[a]; } ! getAttr.call(object, ‘a’) === ‘Jeremiah’; ! getAttr.apply(object, [‘b’]) === ‘Baruch’;
  • 22.
    Can I instantiatea function?
  • 23.
    function Pioneer(){ this.name ="Pioneer"; } ! joe = Pioneer(); joe === undefined; ! joe = new Pioneer(); joe.name == "Pioneer";
  • 24.
    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;
  • 25.
    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;
  • 26.
    Can I builda function with variable number of arguments?
  • 27.
    var object ={a: ‘Jeremiah’, b: ‘Baruch’}; ! function getAttr(a){ return this[a]; } ! getAttr.apply(object, [‘b’]) === ‘Baruch’;
  • 28.
    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’];
  • 29.
    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);
  • 30.
    function smallest() { returnMath.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);
  • 31.
    function highest(){ return arguments.sort(function(a,b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3;
  • 32.
    function highest(){ return arguments.sort(function(a,b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3; // Fatal Error.
  • 33.
  • 34.
    function highest() { varargArray = Array().slice.call(arguments); return argArray.sort(function(a, b) { return b - a; }); } ! highest(1, 1, 2, 3)[0] === 3;
  • 35.
  • 36.
    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); }
  • 37.
    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); }
  • 38.
    ! for ( vard = 0; d < 3; d++ ) { setTimeout(function(){ assert( d == 3, "Check the value of d." ); }, 100); }
  • 39.
    for (var d= 0; d < 3; d++) { (function (d) { setTimeout(function () { console.log(d); }, 100); }(d)); }
  • 40.
    Code smell: Don’tmake closures inside a loop. Normally.
  • 41.
    How do Imake a class?
  • 42.
    #!/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();
  • 43.
    #!/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();
  • 44.
  • 45.
    var Pioneer =function(name) { this.name = name; this.bibleStudies = 0; ! this.preach = function() { this.bibleStudies++; }; }; ! joe = new Pioneer(“Joe”); joe.preach();
  • 46.
    var Pioneer =function(name) { this.name = name; this.bibleStudies = 0; }; ! Pioneer.prototype = {}; Pioneer.prototype.preach = function() { this.bibleStudies++; }; ! joe = new Pioneer(“Joe”); joe.preach();
  • 47.
  • 48.
    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();
  • 49.
  • 50.
    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;
  • 51.
    function bind(context, name){ returnfunction() { 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;
  • 52.
    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;
  • 53.
    Back to ouroriginal goal
  • 54.
    // The .bindmethod 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) ) ); }; };
  • 55.
    Function.prototype.bind = function(){ varfn = 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!”
  • 57.
    Functions can bedefined 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.
  • 58.
  • 59.
    Javascript is agreat, 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.
  • 60.
  • 61.
    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();
  • 62.
  • 63.
    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