70
JavaScript: A Language of Many Contrasts Douglas Crockford Yahoo! http://javascript.crockford.com/ajaxworld.ppt

Ajax World

Embed Size (px)

Citation preview

Page 1: Ajax World

JavaScript:A Language of Many Contrasts

Douglas CrockfordYahoo!

http://javascript.crockford.com/ajaxworld.ppt

Page 2: Ajax World

The World's Most Misunderstood Programming

Language

Page 3: Ajax World

Sources of Misunderstanding• The Name• Mispositioning• Design Errors• Bad Implementations• The Browser• Bad Books• Substandard Standard• JavaScript is a Functional Language

Page 4: Ajax World

Key Ideas• Load and go delivery• Loose typing• Objects as general containers• Prototypal inheritance• Lambda• Linkage through global variables

Page 5: Ajax World

Key Ideas• Load and go delivery• Loose typing• Objects as general containers• Prototypal inheritance• Lambda• Linkage though global variables

Page 6: Ajax World

It is full of warts.

Page 7: Ajax World

For statement• Iterate through all of the members of an

object:

for (var name in object) { if (object.hasOwnProperty(name)) {

// within the loop, // name is the key of current member // object[name] is the current value

}}

Page 8: Ajax World

typeof

• The typeof prefix operator returns a string identifying the type of a value.

type typeofobject 'object'function 'function'array 'object'number 'number'string 'string'boolean 'boolean'null 'object'undefined 'undefined'

Page 9: Ajax World

with statement• Intended as a

short-hand

• Ambiguous

• Error-prone

• Don't use it

with (o) { foo = null;}

o.foo = null;

foo = null;

Page 10: Ajax World

It is mostly good stuff.

Page 11: Ajax World

Inner functions• Functions do not all have to be

defined at the top level (or left edge).

• Functions can be defined inside of other functions.

Page 12: Ajax World

Scope• An inner function has access to the

variables and parameters of functions that it is contained within.

• This is known as Static Scoping or Lexical Scoping.

Page 13: Ajax World

Closure• The scope that an inner function

enjoys continues even after the parent functions have returned.

• This is called closure.

Page 14: Ajax World

Example function fade(id) { var dom = document.getElementById(id), level = 1; function step () { var h = level.toString(16); dom.style.backgroundColor = '#FFFF' + h + h; if (level < 15) { level += 1; setTimeout(step, 100); } } setTimeout(step, 100); }

Page 15: Ajax World

Inheritance• Inheritance is object-oriented code

reuse.

• Two Schools:

• Classical

• Prototypal

Page 16: Ajax World

Classical Inheritance• Objects are instances of Classes.

• A Class inherits from another Class.

Page 17: Ajax World

Pseudoclassical• Pseudoclassical looks sort of classical, but

is really prototypal.

• Three mechanisms:

• Constructor functions.

• The prototype member of functions.

• The new operator.

Page 18: Ajax World

Psuedoclassicalfunction Constructor() { this.member = initializer; return this; // optional}

Constructor.prototype.firstMethod = function (a, b) {...};Constructor.prototype.secondMethod = function (c) {...};

var newObject = new Constructor();

Page 19: Ajax World

new operatorvar newObject = new Constructor();

• new Constructor() returns a new object with a link to Constructor.prototype.

Constructor.prototypenewObject

Page 20: Ajax World

Warning• The new operator is required when

calling a Constructor.

• If new is omitted, the global object is clobbered by the constructor, and then the global object is returned instead of a new instance.

Page 21: Ajax World

Syntactic Rat PoisonConstructor. method('first_method', function (a, b) {...}). method('second_method', function (c) {...});-----------------------------------

Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; };

Page 22: Ajax World

Pseudoclassical Inheritance• Classical inheritance can be simulated by

assigning an object created by one constructor to the prototype member of another.

function BiggerConstructor() {...}; BiggerConstructor.prototype = new Constructor();

• This does not work exactly like the classical model.

Page 23: Ajax World

Example

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

Page 24: Ajax World

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructortoString functionprototype

constructortoString function

new Gizmo(string)

Gizmo

Object

Page 25: Ajax World

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructortoString functionprototype

constructortoString function

new Gizmo(string)

Gizmo

Object

Page 26: Ajax World

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructortoString functionprototype

constructortoString function

new Gizmo(string)

Gizmo

Object

Page 27: Ajax World

Inheritance• If we replace the original prototype

object with an instance of an object of another class, then we can inherit another class's stuff.

Page 28: Ajax World

Example

function Hoozit(id) {

this.id = id;

}

Hoozit.prototype = new Gizmo();

Hoozit.prototype.test = function (id) {

return this.id === id;

};

Page 29: Ajax World

Example

prototype

prototype

function Hoozit(id) { this.id = id;}Hoozit.prototype = new Gizmo();Hoozit.prototype.test = function (id) { return this.id === id;};

test function

constructor

constructortoString function

Gizmo

Hoozit

id string

new Hoozit(string)

Page 30: Ajax World

Example

prototype

prototype

function Hoozit(id) { this.id = id;}Hoozit.prototype = new Gizmo();Hoozit.prototype.test = function (id) { return this.id === id;};

test function

constructor

constructortoString function

Gizmo

Hoozit

id string

new Hoozit(string)

Page 31: Ajax World

Prototypal Inheritance• Class-free.• Objects inherit from objects.• An object contains a secret link to

the object it inherits from.

var newObject = object(oldObject);

newObject__proto__

oldObject

Page 32: Ajax World

object function• A prototypal inheritance language

should have an operator like the object function, which makes a new object using an existing object as its prototype.

Page 33: Ajax World

object function function object(o) { function F() {} F.prototype = o; return new F(); }

Page 34: Ajax World

object function

prototype

F

function object(o) { function F() {} F.prototype = o; return new F();

} newObject = object(oldObject)

constructor

Page 35: Ajax World

object function

prototype

F

function object(o) { function F() {} F.prototype = o; return new F();

} newObject = object(oldObject)

oldObject

constructor

Page 36: Ajax World

object function

prototype

F

newObject

function object(o) { function F() {} F.prototype = o; return new F();

} newObject = object(oldObject)

oldObject

Page 37: Ajax World

object function

newObject

function object(o) { function F() {} F.prototype = o; return new F();

} newObject = object(oldObject)

oldObject

Page 38: Ajax World

Prototypal Inheritancevar oldObject = { firstMethod: function () {...}, secondMethod: function () {...}};

var newObject = object(oldObject);

newObject.thirdMethod = function () {...};

var myDoppelganger = object(newObject);

myDoppelganger.firstMethod();

Page 39: Ajax World

Prototypal Inheritance• There is no limit to the length of the

chain (except common sense).

oldObject

myDoppelganger = object(newObject);

newObject

Page 40: Ajax World

Augmentation• Using the object function, we can

quickly produce new objects that have the same state and behavior as existing objects.

• We can then augment each of the instances by assigning new methods and members.

Page 41: Ajax World

Public Method• A Public Method is a function that

uses this to access its object.• This binding of this to an object

happens at invocation time.• A Public Method can be reused with

many "classes".

Page 42: Ajax World

Public MethodsmyObject.method = function (string) { return this.member + string;};

• We can put this function in any object at it works.

• Public methods work extremely well with prototypal inheritance and with pseudoclassical inheritance.

Page 43: Ajax World

Singletons• There is no need to produce a class-

like constructor for an object that will have exactly one instance.

• Instead, simply use an object literal.

Page 44: Ajax World

Singletonsvar singleton = { firstMethod: function (a, b) { ... }, secondMethod: function (c) { ... }};

Page 45: Ajax World

Functions are used as

• Functions• Methods• Constructors• Classes• Modules

Page 46: Ajax World

Module• Variables defined in a module are only

visible in the module.

• Functions have scope.

• Variables defined in a function only visible in the function.

• Functions can be used a module containers.

Page 47: Ajax World

Global variables are evil• Functions within an application can

clobber each other.

• Cooperating applications can clobber each other.

• Use of the global namespace must be minimized.

Page 48: Ajax World

Singletons• The methods of a singleton can enjoy

access to shared private data and private methods.

Page 49: Ajax World

Singletonsvar singleton = function () { var privateVariable; function privateFunction(x) { ...privateVariable... }

return { firstMethod: function (a, b) { ...privateVariable... }, secondMethod: function (c) { ...privateFunction()... } };}();

Page 50: Ajax World

Applications are Singletonsvar AJAX = function () { var privateVariable; function privateFunction(x) { ...privateVariable... }

return { firstMethod: function (a, b) { ...privateVariable... }, secondMethod: function (c) { ...privateFunction()... } };}();

Page 51: Ajax World

Privacy• All members of an object are public.

• We want private variables and private methods.

• Really.

Page 52: Ajax World

Privileged Method• A Privileged Method is a function that has

access to secret information.

• A Privileged Method has access to private variables and private methods.

• A Privileged Method obtains its secret information through closure.

Page 53: Ajax World

Power Constructor• Put the singleton module pattern in

constructor function, and we have a power constructor pattern.

1. Make a new object somehow.

2. Augment it.

3. Return it.

Page 54: Ajax World

Power Constructorfunction powerConstructor() { var that = object(oldObject), privateVariable; function privateFunction(x) { ... }

that.firstMethod = function (a, b) { ...privateVariable... }; that.secondMethod = function (c) { ...privateFunction()... }; return that;}

Page 55: Ajax World

Power Constructor• Public methods (from the prototype)

var that = object(oldObject);• Private variables (var)• Private methods (inner functions)• Privileged methods • No need to use new

myObject = power_constructor();

Page 56: Ajax World

Parasitic Inheritance• A power constructor calls another

constructor, takes the result, augments it, and returns it as though it did all the work.

Page 57: Ajax World

Psudeoclassical Inheritancefunction Gizmo(id) { this.id = id;}Gizmo.prototype.toString = function () { return "gizmo " + this.id;};

function Hoozit(id) { this.id = id;}Hoozit.prototype = new Gizmo();Hoozit.prototype.test = function (id) { return this.id === id;}

Page 58: Ajax World

Parasitic Inheritancefunction gizmo(id) { return { id: id, toString: function () { return "gizmo " + this.id; } };}

function hoozit(id) { var that = gizmo(id); that.test = function (testid) { return testid === this.id; }; return that;}

Page 59: Ajax World

Secretsfunction gizmo(id) { return { toString: function () { return "gizmo " + id; } };}

function hoozit(id) { var that = gizmo(id); that.test = function (testid) { return testid === id; }; return that;}

Page 60: Ajax World

Shared Secretsfunction gizmo(id, secret) { secret = secret || {}; secret.id = id; return { toString: function () { return "gizmo " + secret.id; }; };}

function hoozit(id) { var secret = {}, that = gizmo(id, secret); that.test = function (testid) { return testid === secret.id; }; return that;}

Page 61: Ajax World

Super Methodsfunction hoozit(id) { var secret = {}, that = gizmo(id, secret), super_toString = that.toString; that.test = function (testid) { return testid === secret.id; }; that.toString = function () { return super_toString.apply(that, []); }; return that;}

Page 62: Ajax World

Inheritance Patterns• Prototypal Inheritance works really

well with public methods.

• Parasitic Inheritance works really well with privileged and private and public methods.

• Pseudoclassical Inheritance for elderly programmers who are old and set in their ways.

Page 63: Ajax World

Working with the Grain• Pseudoclassical patterns are less

effective than prototypal patterns or parasitic patterns.

• Formal classes are not needed for reuse or extension.

• Be shallow. Deep hierarchies are not effective.

Page 64: Ajax World

Performance• Provide a good experience.

• Be respectful of our customer's time.

• Hoare's Dictum: Premature optimization is the root of all evil.

Page 65: Ajax World

Efficiency• The first priority must always be

correctness.

• Optimize when necessary.

• Consider algorithmic improvements O (n) v O (n log n) v O (n2)

• Watch for limits.

Page 66: Ajax World

Minification vs Obfuscation• Reduce the amount of source code to

reduce download time.• Minification deletes whitespace and

comments.• Obfuscation also changes the names

of things.• Obfuscation can introduce bugs.• Never use tools that cause bugs if

you can avoid it. http://www.crockford.com/javascript/jsmin.html

Page 67: Ajax World

Code Conventions for the JavaScript Programming

Language

http://javascript.crockford.com/code.html

Page 68: Ajax World

JSLint• JSLint can help improve the robustness

and portability of your programs.• It enforces style rules.• It can spot some errors that are very

difficult to find in debugging.• It can help eliminate implied globals.• Commandline versions.• In text editors and Eclipse.

Page 69: Ajax World

JSLint• Warning: JSLint will hurt your

feelings.

• If you follow its advice, JSLint will make your programs better.

•http://www.JSLint.com/

Page 70: Ajax World

JavaScript:A Language of Many Contrasts

Douglas CrockfordYahoo!

http://javascript.crockford.com/ajaxworld.ppt