Ajaxworld

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

description

The World's Most Misunderstood Programming Language

Transcript of Ajaxworld

Page 1: Ajaxworld

JavaScript:A Language of Many Contrasts

Douglas CrockfordYahoo!

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

Page 2: Ajaxworld

The World's Most Misunderstood Programming

Language

Page 3: Ajaxworld

Sources of Misunderstanding

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

Page 4: Ajaxworld

Key Ideas

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

Page 5: Ajaxworld

Key Ideas

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

Page 6: Ajaxworld

It is full of warts.

Page 7: Ajaxworld

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: Ajaxworld

typeof

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

type typeof

object 'object'

function 'function'

array 'object'

number 'number'

string 'string'

boolean 'boolean'

null 'object'

undefined 'undefined'

Page 9: Ajaxworld

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: Ajaxworld

It is mostly good stuff.

Page 11: Ajaxworld

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: Ajaxworld

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: Ajaxworld

Closure

• The scope that an inner function enjoys continues even after the parent functions have returned.

• This is called closure.

Page 14: Ajaxworld

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: Ajaxworld

Inheritance

• Inheritance is object-oriented code reuse.

• Two Schools:

• Classical

• Prototypal

Page 16: Ajaxworld

Classical Inheritance

• Objects are instances of Classes.

• A Class inherits from another Class.

Page 17: Ajaxworld

Pseudoclassical

• Pseudoclassical looks sort of classical, but is really prototypal.

• Three mechanisms:

• Constructor functions.

• The prototype member of functions.

• The new operator.

Page 18: Ajaxworld

Psuedoclassical

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

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

var newObject = new Constructor();

Page 19: Ajaxworld

new operator

var newObject = new Constructor();

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

Constructor.prototypenewObject

Page 20: Ajaxworld

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: Ajaxworld

Syntactic Rat Poison

Constructor. 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: Ajaxworld

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: Ajaxworld

Example

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

Page 24: Ajaxworld

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructor

toString functionprototype

constructor

toString function

new Gizmo(string)

Gizmo

Object

Page 25: Ajaxworld

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructor

toString functionprototype

constructor

toString function

new Gizmo(string)

Gizmo

Object

Page 26: Ajaxworld

Example

prototype

id string

function Gizmo(id) {

this.id = id;

}

Gizmo.prototype.toString = function () {

return "gizmo " + this.id;

};

constructor

toString functionprototype

constructor

toString function

new Gizmo(string)

Gizmo

Object

Page 27: Ajaxworld

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: Ajaxworld

Example

function Hoozit(id) {

this.id = id;

}

Hoozit.prototype = new Gizmo();

Hoozit.prototype.test = function (id) {

return this.id === id;

};

Page 29: Ajaxworld

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

constructor

toString function

Gizmo

Hoozit

id string

new Hoozit(string)

Page 30: Ajaxworld

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

constructor

toString function

Gizmo

Hoozit

id string

new Hoozit(string)

Page 31: Ajaxworld

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: Ajaxworld

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: Ajaxworld

object function

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

Page 34: Ajaxworld

object function

prototype

F

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

} newObject = object(oldObject)

constructor

Page 35: Ajaxworld

object function

prototype

F

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

} newObject = object(oldObject)

oldObject

constructor

Page 36: Ajaxworld

object function

prototype

F

newObject

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

} newObject = object(oldObject)

oldObject

Page 37: Ajaxworld

object function

newObject

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

} newObject = object(oldObject)

oldObject

Page 38: Ajaxworld

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

var newObject = object(oldObject);

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

var myDoppelganger = object(newObject);

myDoppelganger.firstMethod();

Page 39: Ajaxworld

Prototypal Inheritance

• There is no limit to the length of the chain (except common sense).

oldObject

myDoppelganger = object(newObject);

newObject

Page 40: Ajaxworld

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: Ajaxworld

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: Ajaxworld

Public Methods

myObject.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: Ajaxworld

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: Ajaxworld

Singletons

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

Page 45: Ajaxworld

Functions are used as

• Functions

• Methods

• Constructors

• Classes

• Modules

Page 46: Ajaxworld

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: Ajaxworld

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: Ajaxworld

Singletons

• The methods of a singleton can enjoy access to shared private data and private methods.

Page 49: Ajaxworld

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

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

Page 50: Ajaxworld

Applications are Singletons

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

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

Page 51: Ajaxworld

Privacy

• All members of an object are public.

• We want private variables and private methods.

• Really.

Page 52: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

Psudeoclassical Inheritance

function 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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

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: Ajaxworld

Code Conventions for the JavaScript Programming

Language

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

Page 68: Ajaxworld

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: Ajaxworld

JSLint

• Warning: JSLint will hurt your feelings.

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

• http://www.JSLint.com/

Page 70: Ajaxworld

JavaScript:A Language of Many Contrasts

Douglas CrockfordYahoo!

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