javascript: the good parts (book report)kahl/cas706/2010/pres/js... · 2010-11-18 · prototypical...

38
JavaScript: The Good Parts (Book Report) Michal Dobrogost November 18th, 2010

Upload: others

Post on 20-Jun-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

JavaScript: The Good Parts (Book Report)

Michal Dobrogost

November 18th, 2010

Page 2: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Introducing JavaScriptHistory

I Java(tm) applets failed, JavaScript took over

I Shunted from non-existance to world wide useI Bad parts resulting from

I Poor specification =⇒ poor portabilityI Difficult to read and modify codeI Design mistakes

I “Beautiful, elegant, highly expressive language” buried inside

Page 3: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Introducing JavaScriptFeatures

Distinguishing features of JavaScript

I Dynamic typing

I First class functions

I Object literal notation

I Prototypal inheritance

Page 4: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Introducing JavaScriptHello World!

-----------------------------------------

hello.html:

-----------------------------------------

<html><body>

<script src="hello.js">

</script>

</body></html>

-----------------------------------------

hello.js:

-----------------------------------------

document.writeln(’Hello world!’);

Page 5: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxBasics

I Comments : C-Style // or /* */ pairsI Do not use /* */ because they can occur in the program

/*

var x = /y*/.exec("yyyyyyy");

*/

I Names : letter (letter | digit | )*

I Numbers : 23, 1.7, 1.1e-10, NaN, Infinity

I Strings : Unicode character set

"d" + ’o’ + "g" + ’\t’ === ’dog\t’

I Boolean false : false, null, undefined, ””, 0, NaN

I Boolean true : everything else

Page 6: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxStatements

I Variable declaration

var x = 3, y = 1, z = 4;

I If

if (x === 4) {

<statements>

} else {

<statements>

}

I Switch

switch (x + y) {

case 0:

case 0 + 1:

y = 3; // <statements>

break // <disruptive>

}

Page 7: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxLoops

I For, while and do while loops similar to C

for (i = 0; i < 10; i += 1) {

<statements>

}

I For-in loop

for (x in xs) {

// Ensure x not from prototype chain

if (xs.hasownProperty(x)) {

...

}

}

Page 8: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxExceptions, Functions

try {

throw "ERROR";

}

catch (e) {

if (e === "ERROR") {

...

}

}

function f(x,y) {

var z = x + y;

return z;

}

Page 9: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxExpressions

Railroad diagram from [1].

I prefix : typeof, + (to number), - (negate), ! (logical not)

I conditional : < expr > ? < expr > : < expr >

I invocation : function(< expr >,< expr >)

I refinement : record.property, array[< expr >]

Page 10: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxLiterals

Literals specify an object inline in the code.

I object : { name : ”bob”, ’age’ : 37 }I array : [1,1,2,3,5,8]I regexp : /[abc]*/ g i m

I g =⇒ global, match multiple timesI i =⇒ case insensitiveI m =⇒ multiline

Page 11: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

SyntaxLiterals

Literals specify an object inline in the code.

I object : { name : ”bob”, ’age’ : 37 }I array : [1,1,2,3,5,8]I regexp : /[abc]*/ g i m

I g =⇒ global, match multiple timesI i =⇒ case insensitiveI m =⇒ multiline

Page 12: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsDefining, in detail

I Objects are passed by reference

I Reserved keywords are enclosed in ”” when used as propertiesof objects.

var delivery = {

"for" : "Dr. Kahl",

from : "Michal"

};

I Reserved keywords accessed by [”property”].

if (delivery.from === "Michal" &&

delivery["for"] === "Dr. Kahl")

{

...

}

Page 13: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsNon-existing fields

I Example

var delivery = {

"for" : "Dr. Kahl",

from : "Michal"

};

I Accessing non-existing property results in undefined .

delivery.contents // results in undefined

I Default values

delivery.contents || "none"

I Guarded retrieval (prevent throwing TypeError)

delivery.contents && delivery.contents.grade

Page 14: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsUpdates

I Example

var delivery = {

"for" : "Dr. Kahl",

from : "Michal"

};

I Change a property of the object

delivery.from = "Michal Dobrogost"

I Add a property to the object

delivery.contents = {

material : "presentation.tex",

grade : "A+"

}

I Removing a property from the object

delete delivery.contents.grade

Page 15: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsPrototypical inheritance

I All objects subclass Object.prototype by default

I Prototype selected at creation time

I To sidestep complexities, Crockford suggests

if (typeof Object.beget !== ’function’) {

Object.beget = function(o) {

var f = function () {};

f.prototype = o;

return new f();

}

}

Page 16: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsInheritance example

var parent = { bye : "world" };

var child = Object.beget(parent);

child.hi = "Maggie";

parent.bye = "Ashley";

var str = ’Goodbye ’ + child.bye + ’, hello ’ + child.hi;

document.writeln(str + "!");

Prints...

“Goodbye Ashley, hello Maggie!”.

Page 17: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsInheritance example

var parent = { bye : "world" };

var child = Object.beget(parent);

child.hi = "Maggie";

parent.bye = "Ashley";

var str = ’Goodbye ’ + child.bye + ’, hello ’ + child.hi;

document.writeln(str + "!");

Prints... “Goodbye Ashley, hello Maggie!”.

Page 18: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsReflection & Enumeration

for (prop in child) {

document.writeln("prop:" + prop);

document.writeln("own:" + child.hasOwnProperty(prop));

document.writeln("type:" + (typeof child[prop]));

document.writeln("val:" + child[prop]);

}

// prop:hi other types: number

// own:true string

// type:string object

// val:Maggie function

// undefined

// prop:bye

// own:false

// type:string

// val:Ashley

Page 19: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

ObjectsNamespaces

No module or namespace facilities =⇒ fake it!

// Single global variable, our "namespace"

var NAMESP = {}

// All others are properties

NAMESP.parent = { bye : "world" };

NAMESP.child = Object.beget(NAMESP.parent);

NAMESP.child.hi = "Maggie";

NAMESP.parent.bye = "Ashley";

Page 20: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas Methods

I Functions that are properties of objects are methodsI All functions take an implicit ’this’ argument

I Bound at invocation time.

I For methods ’this’ binds to the containing object

var counter = {

val : 0,

inc : function () {

this.val += 1;

}

};

Page 21: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas Functions

I Functions that are not methods bind ’this’ to the global objectI Crockford: This is a design mistake for inner functions

I Should bind to the invoking function’s ’this’

var counter = {

val : 0,

inc : function (howmuch) {

var incOnce = function () {

this.val += 1; // Problem!

}

for (i = 0; i < howmuch; i += 1) {

incOnce();

}

}

};

Page 22: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas Functions (’that’ pattern)

I Solved by introducing a variable ’that’

I Inner function is closure =⇒ ’that’ is visible

var counter = {

val : 0,

inc : function (howmuch) {

var that = this; // Solved!

var incOnce = function () {

that.val += 1; // Solved!

}

for (i = 0; i < howmuch; i += 1) {

incOnce();

}

}

};

Page 23: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas Constructors

I Functions invoked with ’new’ serve as constructors

I Bind ’this’ to the object being created

var MakeHello = function () {

this.hello = "world";

}

var x = new MakeHello();

document.writeln("Hello " + x.hello + "!");

Page 24: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas Constructors (with inheritance)

I Functions subclass Function.prototypeI prototype property sets prototype for created object

I Now we can understand the beget function

if (typeof Object.beget !== ’function’) {

Object.beget = function(o) {

var f = function () {}; // returns new object

f.prototype = o;

return new f();

}

}

Page 25: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Functionsas invoked by apply

I Functions have apply propertyI apply is a method of Function.prototypeI Takes the object to bind as ’this’I Takes the an array of arguments

var sum = add.apply(null, [5,8]);

I Can be used to apply methods with ’this’ bound differently

var sister = {

msg : "I like blue"

show : function () { document.writeln(this.msg); }

};

var brother = { msg : "I like yellow" };

sister.show.apply(brother);

Page 26: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

FunctionsScope, closures and currying

I Despite C-like syntax, a block does not start a new scope

I Inner functions have access to variables in scope at definition

var add = function(x) {

{

var z = x;

}

return function (y) { return z + y; }

}

var inc = add(1);

document.writeln(inc(11));

Prints... 12

Page 27: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Augmenting types

We can extend the functionality of a whole class of objects.

I functions

I strings

I numbers

I regular expressions

I booleans

Number.prototype.toInteger = function () {

return Math[this < 0 ? ’ceiling’ : ’floor’](this);

}

document.writeln( (-1.5).toInteger() );

Prints... -1

Page 28: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(i) Hello world, gone wrong 1

if ([0] == false) { document.writeln(’Hello’); }

if ([0]) { document.writeln(’world’); }

Prints...

Hello

world

Because...

I Type conversion results in 0 === 0

I [0] is an object so it is not false

1Idea from http://jimbojw.com [3]

Page 29: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(i) Hello world, gone wrong 1

if ([0] == false) { document.writeln(’Hello’); }

if ([0]) { document.writeln(’world’); }

Prints...

Hello

world

Because...

I Type conversion results in 0 === 0

I [0] is an object so it is not false

1Idea from http://jimbojw.com [3]

Page 30: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(i) Hello world, gone wrong 1

if ([0] == false) { document.writeln(’Hello’); }

if ([0]) { document.writeln(’world’); }

Prints...

Hello

world

Because...

I Type conversion results in 0 === 0

I [0] is an object so it is not false

1Idea from http://jimbojw.com [3]

Page 31: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(ii)

function fib(x) {

if (x <= 1) { return x; }

return

fib(x - 1) + fib(x - 2);

}

document.writeln(fib(1000));

What happens?

Prints undefinedBecause... JavaScript sees

function fib (x) {

if (x <= 0) { return 0; }

return;

fib (x - 1) + fib(x - 2);

}

Page 32: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(ii)

function fib(x) {

if (x <= 1) { return x; }

return

fib(x - 1) + fib(x - 2);

}

document.writeln(fib(1000));

What happens? Prints undefinedBecause...

JavaScript sees

function fib (x) {

if (x <= 0) { return 0; }

return;

fib (x - 1) + fib(x - 2);

}

Page 33: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(ii)

function fib(x) {

if (x <= 1) { return x; }

return

fib(x - 1) + fib(x - 2);

}

document.writeln(fib(1000));

What happens? Prints undefinedBecause... JavaScript sees

function fib (x) {

if (x <= 0) { return 0; }

return;

fib (x - 1) + fib(x - 2);

}

Page 34: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(iii)

document.writeln(’4’ - 2);

document.writeln(’4’ + 2);

Prints...

2

42

Because...

I typeof ’4’ === ’string’

I So + acts as string concatenation

Page 35: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(iii)

document.writeln(’4’ - 2);

document.writeln(’4’ + 2);

Prints...

2

42

Because...

I typeof ’4’ === ’string’

I So + acts as string concatenation

Page 36: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

The Bad Parts(iii)

document.writeln(’4’ - 2);

document.writeln(’4’ + 2);

Prints...

2

42

Because...

I typeof ’4’ === ’string’

I So + acts as string concatenation

Page 37: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

Douglas Crockford, JavaScript: The Good Parts. O’Reilly,2008.

ECMA International, ECMAScript Language Specification 5thedition 2009-12. http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf

JimboJW stackoverflow.com : Why does 2 == [2] inJavaScript? 2009-11-14. http://stackoverflow.com/questions/1724255/why-does-2-2-in-javascript

Page 38: JavaScript: The Good Parts (Book Report)kahl/CAS706/2010/Pres/JS... · 2010-11-18 · Prototypical inheritance I All objects subclass Object.prototype by default ... I apply is a

THANK YOU