object oriented javascript

52
Object Oriented JavaScript Mike Girouard — AJAXWorld 2009

Upload: michael-girouard

Post on 11-May-2015

4.723 views

Category:

Technology


2 download

DESCRIPTION

My talk for AJAXWorld 2009 in NYC.

TRANSCRIPT

Page 1: Object Oriented JavaScript

Object Oriented JavaScriptMike Girouard — AJAXWorld 2009

Page 2: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Today’s Agenda

JavaScript Object ModelTypes, Constructors, Inheritance

“Missing” FeaturesNamespaces, Visibility, Polymorphism

Useful Design PatternsFactories, Singletons, Modules

Page 3: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

The JavaScript Object Model

Page 4: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Boolean

Object

Number String Array Date

RegExp Function Math Error EvalError

RangeError ReferenceError SyntaxError TypeError URIError

Primitive Types

Page 5: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Creating Custom Types

Object constructors are functions

Defining a new type is as simple as defining a function

Creating a new instance is simply invoking a function with the new prefix

Page 6: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

// Define the constructorvar Timestamp = function () { this.value = new Date().getTime();};

// Instantiatevar ts = new Timestamp;

// Read instance variableconsole.log(ts.value);

Creating Custom Types

Page 7: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Instance Members

Instance members are defined in a constructor’s prototype object

New instances will have access to prototype members

Prototypes may be modified at runtime

Page 8: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Timestamp = function () { this.value = new Date().getTime();};

Timestamp.prototype.getValue = function () { return this.value;};

var ts = new Timestamp;console.log(ts.getValue());

Instance Members

Page 9: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Timestamp = function () { this.value = new Date().getTime();};

var ts = new Timestamp;

Timestamp.prototype.getValue = function () { return this.value;};

console.log(ts.getValue()); // Still works

Instance Members

Page 10: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Inheritance

Page 11: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Prototypal Inheritance

Completely eliminates the need for classes

Objects inherit directly from other objects (prototypes)

Incredibly efficient, ridiculously strange

Page 12: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Foo = function () {}; // Foo Constructorvar Bar = function () {}; // Bar ConstructorBar.prototype = new Foo; // Bar extends Foo

var f = new Foo(); // Foo instancevar b = new Bar(); // Bar instance

console.log(f instanceof Foo); // trueconsole.log(f instanceof Bar); // falseconsole.log(b instanceof Foo); // trueconsole.log(b instanceof Bar); // true

Prototypal Inheritance

Page 13: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Classical Inheritance

JavaScript has no native support for classical inheritance

Many libraries support class-like structures

Rolling your own is quite trivial

Page 14: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Foo = classFactory({ __construct: function () { this.identify(); },

identify: function () { console.log(‘Foo’); }});

Classical Inheritance

Page 15: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Bar = Foo.extend({ identify: function () { console.log(‘Bar’); }});

Classical Inheritance

Page 16: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var classFactory = function (obj, extends) { if (extends) for (var i in extends) if (!obj[i]) obj[i] = extends[i];

if (obj.__construct) obj.__construct.call(obj); obj.extend = function (subclass) { return classFactory(subclass, obj); };

return obj;};

Classical Inheritance

Page 17: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

“Missing” Features

Page 18: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Namespaces

Page 19: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Why bother?

JavaScript has implied global scope

Global variables are only for selfish people

Raise your hand if you use these variable names:

id, element, name, value, target…

Page 20: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Implementing namespaces

Use an object… any object

Remember:Objects can store any kind of value

Everything is an object

This means anything [mutable] can be a namespace

Page 21: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var mikeg = { name : ‘Mike G’, location : ‘NYC’,

getName : function () { return this.name; }, getLocation : function () { return location; }};

Namespace Objects

Page 22: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var getXHR = function () { if (!getXHR.enabled) return null; var xhr = new XMLHttpRequest; getXHR.registry.push(xhr);

return xhr;};

getXHR.registry = [];getXHR.enabled = true;

Namespace Functions

Page 23: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Visibility

Page 24: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Data Hiding in JS

There is no concept of public, private, or protected in JavaScript

Closures allow values to be remembered in a function, even after it terminates

Page 25: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var Person = function (name) { this.getName = function () { return name; };

this.setName = function (newName) { return name = newName; };};

Data Hiding in JS

Page 26: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

// Assume: Person

var mike = new Person(‘Mike G.’);var alex = new Person(‘Alex H.’);

console.log(mike.name); // undefinedconsole.log(alex.name); // undefined

console.log(mike.getName()); // Mike G.console.log(alex.getName()); // Alex H.

Data Hiding in JS

Page 27: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Polymorphism

Page 28: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Easier than you think…

Because JavaScript is a dynamic language, polymorphism is quite easy and very common.

Two common types of polymorphism:1. Runtime Replacement

2. Loadtime Branching

Page 29: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var getXHR = function () { if (window.XMLHttpRequest) { return function () { // Return a standard XHR instance }; } else { return function () { // Return an Explorer XHR instance }; }}(); // Note: parens trigger self-invocation

Loadtime Branching

Page 30: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var documentListFactory = function () { var out = []; // Just a simple array

// Override the default .push() method out.push = function (document) { Array.prototype.push.call(out, { document : document, timespamp : new Date().getTime() }); };

return out;};

Runtime Replacement

Page 31: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Useful Design Patterns

Page 32: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Factories

Page 33: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

You Need Factories

Forgetting the new keyword will break your application.

The issue comes down to the implied global scope

Using new, context = the instance

Forgetting new, context = window

Page 34: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var DocumentCreator = function (document) { // What does ‘this’ refer to? this.document = document;};

new DocumentCreator(‘foo.txt’); // InstanceDocumentCreator(‘foo.txt’); // window

Brittle Constructor

Page 35: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var DocumentCreator = function (document) { // Yes, constructors can have return values :) return DocumentCreator.factory(document);};

DocumentCreator.factory = function (document) { return new DocumentCreator(document);};

new DocumentCreator(‘foo.txt’); // InstanceDocumentCreator(‘foo.txt’); // Instance

A Simple Factory

Page 36: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Singletons

Page 37: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Singletons are Easy Too

Nothing more than a simple object literal

Objects are always passed by reference and values are static

Very useful for grouping items together, even if they exist in other objects

Page 38: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var myHttpLibrary = { newXHR : function (params) { ... }, parseQueryString : function (qs) { ... }, createQueryString : function (qs) { ... }};

Singletons

Page 39: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

The Module

Page 40: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

A Visibility Pattern

Original pattern discovered by Douglas Crockford

Simplifies private data in JS

Page 41: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var config = function () { var data = {}; return { get : function (name) { return data[name]; }, set : function (name, value) { data[name] = value; return this.get(name); } };}();

A Simple Module

Page 42: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

// Assume: config

config.set(‘name’, ‘Mike G.’);

console.log(config.data.name); // undefinedconsole.log(config.get(‘name’)); // Mike G.

A Simple Module

Page 43: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var config = function () { var me, data = {}; return me = { get : function (name) { return data[name] }, set : function (name, value) { data[name] = value; return me.get(name); } };}();

A Better Module

Page 44: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var module = function () { var app, util, service;

app = {};

util = {};

return service = {};}();

Modules for Organization

Page 45: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

var module = function () { var app, util, service;

app = { init : function () { ... } };

util = {};

return service = { init : app.init };}();

Modules for Organization

Page 46: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Any questions so far?

Page 47: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Miscellaneous…

Everything in JavaScript is an object

All objects can be enumerated via for…in

The for…in construct sees all the way up the prototype chain

myObject.hasOwnProperty(‘foo’) is gross but necessary

Page 48: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Miscellaneous…

Most primitives have literals

Primitive constructors aren’t called in literals (IE: no prototype features added)

Please don’t go modifying primitive prototypes

Page 49: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Miscellaneous…

Forgetting to use the new keyword in some cases will break your app.

The typeof operator is useful, but lies

The instanceof operator is more accurate

Page 50: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Miscellaneous…

The use of this tempting, but introduces ambiguity into your program

In most cases its not necessary and can be avoided

Page 51: Object Oriented JavaScript

Mike Girouard — AJAXWorld 2009

Miscellaneous…

Most of JavaScript’s OO features are clever functional programming patterns

Studying functional programming languages will make you a better JavaScript programmer

Page 52: Object Oriented JavaScript

Thank [email protected]