Javascriptinobject orientedway-090512225827-phpapp02

105
JavaScript in Object-Oriented Way Chhorn Chamnap May 2009

Transcript of Javascriptinobject orientedway-090512225827-phpapp02

Page 1: Javascriptinobject orientedway-090512225827-phpapp02

JavaScript in Object-Oriented WayChhorn Chamnap

May 2009

Page 2: Javascriptinobject orientedway-090512225827-phpapp02

2

Agenda

Introduction to JavaScript Working with Objects Working with Functions Working with Closures Details of the Object Model

Public Members Private Members Privileged Members Static Members Inheritance

Practical Closures

Page 3: Javascriptinobject orientedway-090512225827-phpapp02

3

Introduction to JavaScript

Page 4: Javascriptinobject orientedway-090512225827-phpapp02

4

Introduction to JavaScript

JavaScript has a reasonable claim to being the world’s most misunderstood programming language.

JavaScript is a scripting language most often used for client-side web development.

Major implementations are SpiderMonkey, Rhino, KJS, JavaScriptCore, and V8.

It is a dynamic, weakly typed, prototype-based language with first-class functions.

Page 5: Javascriptinobject orientedway-090512225827-phpapp02

5

Dynamic Language

A high level of programming languages that execute many common behaviors at runtime. These behaviors could include: Extension of the program, By adding new code, By extending objects and definitions, Or by modifying the type system.

Dynamic languages and dynamic typing are not identical concepts, and a dynamic language need not be dynamically typed, though many dynamic languages are dynamically typed.

Page 6: Javascriptinobject orientedway-090512225827-phpapp02

6

A Loosely Typed Language

In JavaScript, you do not declare a type when defining a variable. However, this does not mean that variables are not typed. Depending on what data it contains, a variable can have one of several types.

A variable can change its type, depending on what value is assigned to it. The primitive datatypes can also be cast from one type to another.

There are three primitive types: booleans, numbers, and strings.

There are functions, which contain executable code. There are objects, which are composite datatypes.

Lastly, there are the null and undefined datatypes. Primitive datatypes are passed by value, while all other datatypes are passed by reference.

Page 7: Javascriptinobject orientedway-090512225827-phpapp02

7

Prototyped-based Programming

A style of object-oriented programming in which classes are not present, and behavior reuse (known as inheritance in class-based languages) is performed via a process of cloning existing objects that serve as prototypes. This model can also be known as class-less, prototype-oriented or instance-based programming.

In prototype-based systems there are two methods of constructing new objects, through cloning of an existing object, and through ex nihilo ("from nothing") object creation.

Page 8: Javascriptinobject orientedway-090512225827-phpapp02

8

Language Features

StructuredJavaScript supports all the structured programming syntax in C (e.g., if statements, while loops, switch statements, etc.). One partial exception is scoping: C-style block-level scoping is not supported. JavaScript 1.7, however, supports block-level scoping with the let keyword. Like C, JavaScript makes a distinction between expressions and statements.

Dynamicdynamic typing

Types are associated with values, not variables.JavaScript supports duck typing.

objects as associative arraysJavaScript is heavily object-based. Objects are associative

arrays. Properties and their values can be added, changed, or deleted at run-time. run-time evaluation JavaScript includes an eval function that can execute statements provided as strings at run-time.

Page 9: Javascriptinobject orientedway-090512225827-phpapp02

9

Language Features (cont.)

Functionalfirst-class functions

Functions are first-class; they are objects themselves. As such, they have properties and can be passed around and interacted with like any other objects.

first-class functions treats functions as first-class objects. Specifically, this means that the language supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions.inner functions and closures

Inner functions (functions defined within other functions) are created each time the outer function is invoked, and variables of the outer functions for that invocation continue to exist as long as the inner functions still exist, even after that invocation is finished (e.g. if the inner function was returned, it still has access to the outer function's variables) — this is the mechanism behind closures within JavaScript.

Page 10: Javascriptinobject orientedway-090512225827-phpapp02

10

Language Features (cont.)

Prototype-basedprototypes

JavaScript uses prototypes instead of classes for defining object properties, including methods, and inheritance. It is possible to simulate many class-based features with prototypes in JavaScript.functions as object constructors Functions double as object constructors along with their typical role. Prefixing a function call with new creates a new object and calls that function with its local this keyword bound to that object for that invocation. The function's prototype property determines the new object's prototype.functions as methods

Unlike many object-oriented languages, there is no distinction between a function definition and a method definition. Rather, the distinction occurs during function calling; a function can be called as a method. When a function is invoked as a method of an object, the function's local this keyword is bound to that object for that invocation.

Page 11: Javascriptinobject orientedway-090512225827-phpapp02

11

Language Features (cont.)

Othersrun-time environment

JavaScript typically relies on a run-time environment (e.g. in a web browser) to provide objects and methods by which scripts can interact with "the outside world". (This is not a language feature, but it is common in most JavaScript implementations.)variadic functions

An indefinite number of parameters can be passed to a function. The function can both access them through formal parameters and the local arguments object.array and object literals

Like many scripting languages, arrays and objects (associative arrays in other languages) can be created with a succinct shortcut syntax. The object literal in particular is the basis of the JSON data format.regular expressions

JavaScript also supports regular expressions in a manner similar to Perl.

Page 12: Javascriptinobject orientedway-090512225827-phpapp02

12

Working with Objects

Page 13: Javascriptinobject orientedway-090512225827-phpapp02

13

Objects

JavaScript is fundamentally about objects. Array are objects. Functions are objects. Objects are objects.

What are objects? Objects are collections of name-value

pairs. The names are strings, and the values are string, numbers, booleans, and objects.

Page 14: Javascriptinobject orientedway-090512225827-phpapp02

14

Objects and Properties

You define a property of an object by assigning it a value.myCar.make = “Ford”;

JavaScript objects are sometimes called associative arrays, since each property is associated with a string value that can be used to access it.

Properties of JavaScript objects can be accessed or set using a dot notation or bracket notation.myCar.make = “Ford”;

or myCar[“make”] = “Ford”;or var propertyName = “make”;

myCar[propertyName] = “Ford”;

Page 15: Javascriptinobject orientedway-090512225827-phpapp02

15

Objects and Properties (cont.)

You can use the bracket notation with for…in to iterate over all the properties of an object.function showProperties(obj, objName) {

var result = “”;

for(var i in obj)

result += objName + “.” + i + “ = “ + obj[i] + “\n”;

return result;

}

myCar.make = Ford

myCar.model = Mustang

myCar.year = 1969

Page 16: Javascriptinobject orientedway-090512225827-phpapp02

16

Creating New Objects

You can create an object using an object initializer.var obj = { property_1: value_1,

property_2: value_2, property_n: value_n };

Alternatively, you can create an object with these two steps:

1. Define the object type by writing a constructor function.

2. Create an instance of the object with new.

Page 17: Javascriptinobject orientedway-090512225827-phpapp02

17

Creating New Objects (cont.)

function Car(make, model, year) {

this.make = make;

this.model = model;

this.year = year;

}

Now, you can create an object called myCar as follows:myCar = new Car(“Eagle”, “Talon TSi”, 1993);

You can create any number of car objects by calls to new.

An object can have a property that is itself another object.

Page 18: Javascriptinobject orientedway-090512225827-phpapp02

18

Indexing Object Properties

In JavaScript 1.1 or later, if you initially define a property by its

name, you must always refer to it by its name, myCar.color = “red”;

and if you initially define a property by an index, you must always refer to it by its index.myCar[5] = “25 mpg”;

Page 19: Javascriptinobject orientedway-090512225827-phpapp02

19

Define Properties for an Object Type You can add a property defined object

by using the prototype property.Car.prototype.color = “red”;

car1.color = “blue”;

This defines a property that is shared by all objects of the specified type, rather than by just one instance of the object.

Page 20: Javascriptinobject orientedway-090512225827-phpapp02

20

Define Methods

A method is a function associated with an object. You define a method by:object.methodname = function_name;

You can then call the method in the context of the object as follows:object.methodname(params);

Page 21: Javascriptinobject orientedway-090512225827-phpapp02

21

Define Methods (cont.)

function displayCar() { return “A beautiful ” + this.year + “ ” +

this.make + “ ” + this.model;}function Car(make, model, year, owner) { this.make = make;

this.model = model; this.year = year; this.owner = owner; this.displayCar = displayCar;

}

car1.displayCar();car2.displayCar();

Page 22: Javascriptinobject orientedway-090512225827-phpapp02

22

Deleting Properties

You can remove a property by using the delete operator.//create a new object with two properties: a and b.myObj = new Object();myObj.a = 5;myObj.b = 12;

delete myObj.a; //remove the a property

Page 23: Javascriptinobject orientedway-090512225827-phpapp02

23

Working with Functions

Page 24: Javascriptinobject orientedway-090512225827-phpapp02

24

Function Object

A JavaScript function can take 0 or more named parameters.

The function body can declare its own variables which are local to that function.

If no return statement is used, JavaScript returns undefined.function add(x, y) {

var total = x + y;return total;

}

Page 25: Javascriptinobject orientedway-090512225827-phpapp02

25

Functions As First-Class Objects

In JavaScript, functions are first-class objects. They can be stored in variables, passed into other functions as arguments, passed out of functions as return values, and constructed at run-time.

You can create anonymous functions, which are functions created using the function() { ... } syntax. They are not given names, but they can be assigned to variables.

JavaScript has function-level scope. JavaScript is also lexically scoped, which means

that functions run in the scope they are defined in, not the scope they are executed in.

Page 26: Javascriptinobject orientedway-090512225827-phpapp02

26

Function Arguments

JavaScript functions can be invoked with any number of arguments, regardless of the number of arguments named in the function definition.

You can call a function without passing the parameters it expects, in which case they will be set to underfined.add(); //NaN

You can also pass in more arguments than the function is expecting:add(2, 3, 4); //5

Page 27: Javascriptinobject orientedway-090512225827-phpapp02

27

The arguments object

Functions have access to an additional variable inside their body called arguments, which is an array-like object holding all of the values passed to the function.function add() {

var sum = 0;for(var i=0; i<arguments.length; i++) {

sum += arguments[i];}return sum;

}

add(2, 3, 4, 5); //14

Page 28: Javascriptinobject orientedway-090512225827-phpapp02

28

The arguments object (cont.)

The arguments object defines a callee property that refers to the function that is currently being executed. This property is rarely useful, but it can be used to allow unnamed functions to invoke themselves recursively.function(x) {

if (x <= 1) return 1;

return x * arguments.callee(x-1);

}

Page 29: Javascriptinobject orientedway-090512225827-phpapp02

29

Functions as Data

In JavaScript, however, functions are also data, which means that they can be assigned to variables, stored in the properties of objects or the elements of arrays, passed as arguments to functions, and so on.

function square(x) { return x*x; }

var a = square(4); // a contains the number 16 var b = square; // Now b refers to squarevar c = b(5); // c contains the number 25

var o = new Object(); o.square = function(x) { return x*x; }y = o.square(16); // y equals 256

Page 30: Javascriptinobject orientedway-090512225827-phpapp02

30

Constructor Functions

A constructor function is a function that initializes the properties of an object and is intended for use with the new operator.

function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner;

}

Page 31: Javascriptinobject orientedway-090512225827-phpapp02

31

Function Properties and Methods

The length property of the arguments array specifies the number of arguments that were passed to the function.

The length property of the Function object returns exactly how many declared parameters a function has.

Note that unlike arguments.length, this length property is available both inside and outside of the function body.function check(args) {

var actual = args.length; var expected = args.callee.length;if (actual != expected) {

throw new Error("Wrong number of arguments: expected: " + expected + "; actually passed " + actual);

}}

Page 32: Javascriptinobject orientedway-090512225827-phpapp02

32

Defining Your Own Function Properties When a function needs to use a variable

whose value persists across invocations, it is often convenient to use a property of the Function object, instead of cluttering up the namespace by defining a global variable.

function counter() {if (!arguments.callee.count) { arguments.callee.count = 0; }return arguments.callee.count++;

}

Page 33: Javascriptinobject orientedway-090512225827-phpapp02

33

The apply() and call() Methods

These methods allow you to invoke a function as if it were a method of some other object.

The first argument to both call() and apply() is the object on which the function is to be invoked; this argument becomes the value of the this keyword within the body of the function.

Any remaining arguments to call() are the values that are passed to the function that is invoked.

Page 34: Javascriptinobject orientedway-090512225827-phpapp02

34

The apply() and call() Methods

f.call(o, 1, 2);

This is similar to the following lines of code:o.m = f;

o.m(1,2);

delete o.m;

The apply() method is like the call() method, except that the arguments to be passed to the function are specified as an array:f.apply(o, [1, 2]);

Page 35: Javascriptinobject orientedway-090512225827-phpapp02

35

Anonymous Functions

An anonymous function, executed immediately.(function() {

var foo = 10;

var bar = 2;

alert(foo * bar);

})();

An anonymous function with arguments.(function(foo, bar) {

alert(foo * bar);

})(10, 2);

An anonymous function that returns a value.var baz = (function(foo, bar) {

return foo * bar;})(10, 2);

Page 36: Javascriptinobject orientedway-090512225827-phpapp02

36

Anonymous Functions (cont.)

Here’s a way of “hiding” some local variables – like block scope in C:

> var a = 1;> var b = 2;> (function() {

var b = 3; a += b;

})();> a4> b2

Page 37: Javascriptinobject orientedway-090512225827-phpapp02

37

Inner Functions

JavaScript function declarations are allowed inside other functions.

An important detail of nested functions in JavaScript is that they can access variables in their parent function’s scope.function betterExampleNeeded() {

var a = 1;function oneMoreThanA() { return a + 1;}return oneMoreThanA();

}

Page 38: Javascriptinobject orientedway-090512225827-phpapp02

38

Working with Closures

Page 39: Javascriptinobject orientedway-090512225827-phpapp02

39

Working with Closures

Closures are often considered an advanced feature in JavaScript, but understanding them is essential to mastering the language.

JavaScript allows inner functions. And that those inner functions are allowed access to all of

the local variables, parameters and declared inner functions within their outer function(s).

A closure is formed when one of those inner functions is made accessible outside of the function in which it was contained, so that it may be executed after the outer function has returned.

At which point it still has access to the local variables, parameters and inner function declarations of its outer function.

Page 40: Javascriptinobject orientedway-090512225827-phpapp02

Working with Closures (cont.)

Consider the following function:function init() {

var name = “Mozilla”;

function displayName() {

alert(name);

}

displayName();

}

Page 41: Javascriptinobject orientedway-090512225827-phpapp02

41

Working with Closures (cont.)

This is an example of lexical scoping: in JavaScript, the scope of a variable is defined by its location within the source code, and nested functions have access to variables declared in their outer scope.

Now consider the following example:function makeFunc() {

var name = “Mozilla”;function displayName() { alert(name);}return displayName;

}var myFunc = makeFunc();myFunc();

Page 42: Javascriptinobject orientedway-090512225827-phpapp02

42

Working with Closures (cont.)

The displayName() inner function was returned from the outer function before being executed.

Normally, the local variables within a function only exist for the duration of that function’s execution. Once makeFunc() has finished executing, it is reasonable to expect that the name variable will no longer be necessary.

Since the code still works as expected, this is obviously not the case.

Page 43: Javascriptinobject orientedway-090512225827-phpapp02

43

Working with Closures (cont.)

A closure is a special kind of object that combines two things: a function, and the environment in which that function was created.

The environment consists of any local variables that were in-scope at the time that the closure was created.

In this case, myFunc is a closure that incorporates both the displayName() and the “Mozilla” string that existed when the closure was created.

Page 44: Javascriptinobject orientedway-090512225827-phpapp02

44

A More Interesting Example

function makeAdder(x) {

return function(y) {

return x + y;

}

}

var add5 = makeAdder(5);

var add10 = makeAdder(10);

console.log(add5(2)); //7

console.log(add10(2)); //12

Page 45: Javascriptinobject orientedway-090512225827-phpapp02

45

A More Interesting Example (cont.) We have defined a function makeAdder(x) which

takes a single argument x and returns a new function. The function it returns takes a single argument y, and returns the sum of x and y.

In essence, makeAdder is a function factory – it creates functions which can add a specific value to their argument.

• add5 and add10 are both closures. They share the same function body definition, but store different environments.

In add5’s environment, x is 5. In add10’s environment, x is 10.

Page 46: Javascriptinobject orientedway-090512225827-phpapp02

46

Details of the Object Model

Page 47: Javascriptinobject orientedway-090512225827-phpapp02

Class-Based vs. Prototype-Based LanguagesClass-Based Prototype-Based

Class and instance are distinct entities.

Define a class with a class definition; instantiate a class with constructor methods.

Create a single object with new operator.

All objects are instances.

Define and create a set of objects with constructor functions.

Same.

Page 48: Javascriptinobject orientedway-090512225827-phpapp02

Class-Based vs. Prototype-Based Languages (cont.) Construct an object

hierarchy by using class definitions to define subclasses of existing classes.

Inherit properties by following the class chain.

Class definition specifies all properties of all instances of a class. Cannot add properties dynamically at run time.

Construct an object hierarchy by assigning an object as the prototype associated with a constructor function.

Inherit properties by following the prototype chain.

Constructor function or prototype specifies an initial set of properties. Can add or remove properties dynamically to individual objects or to the entire set of objects.

Page 49: Javascriptinobject orientedway-090512225827-phpapp02

49

Class-Based vs. Prototype-Based Languages (cont.)

FunctionsMethods

FunctionsConstructors

FunctionsClasses

PrototypicalClassical

DynamicStatic

Loosely-typedStrongly-typed

JavaScriptJava

Page 50: Javascriptinobject orientedway-090512225827-phpapp02

50

Public Members

All of the class’s attributes and methods are public and accessible. The public attributes are created using the this keyword.

There are two main ways of putting members in a new object: In the constructor In the prototype

Page 51: Javascriptinobject orientedway-090512225827-phpapp02

51

In the constructor

This technique is usually used to initialize public instance variables. The constructor’s this variable is used to add members to the object.function Container(param) {

this.member = param;

}

So, if we construct a new objectvar myContainer = new Container(‘abc’);

then myContainer.member contains ‘abc’.

Page 52: Javascriptinobject orientedway-090512225827-phpapp02

52

In the prototype

This technique is usually used to add public methods.

To add a method to all objects made by a constructor, add a function to the constructor’s prototype:Container.prototype.stamp = function(string) {

return this.member + string;}

myContainer.stamp(‘def’); //’abcdef’

Page 53: Javascriptinobject orientedway-090512225827-phpapp02

53

Private Members Using a Naming Convention An underscore is added to the

beginning of each member, signifying that it is intended to be private.

Using an underscore is a well-known naming convention; it says that the attribute (or method) is used internally, and that accessing it or setting it directly may have unintended consequences.

Page 54: Javascriptinobject orientedway-090512225827-phpapp02

54

Private Members Through Closures Private members are made by the

constructor. Ordinary vars and parameters of the constructor becomes the private members.

By convention, we make a private that parameter. This is used to make the object available to the private methods.

Private methods cannot be called by public methods.

Page 55: Javascriptinobject orientedway-090512225827-phpapp02

55

Private Members Through Closures (cont.)

function Container(param) {this.member = param; // Public attribute.var secret = 3; // Private attribute.var that = this; // Private attribute.

function dec() { // Private method....}

}

//Public method.Container.prototype.stamp = function() {...};

Page 56: Javascriptinobject orientedway-090512225827-phpapp02

56

Privileged Members

A privileged method is able to access the private variables and methods, and is itself accessible to public methods and the outside.

Page 57: Javascriptinobject orientedway-090512225827-phpapp02

57

Privileged Members

function Container(param) {this.member = param; // Public attribute.var secret = 3; // Private attribute.var that = this; // Private attribute.

function dec() { // Private method.if(secret > 0) { secret -= 1; return true;} else { return false;}

}

this.service = function() { //Privileged method.if(dec()) { return that.member;} else { return null;}

};}

Page 58: Javascriptinobject orientedway-090512225827-phpapp02

58

Static Members

Static members operate on the class-level instead of the instance-level; there is only one copy of each static member.

These private static members can be accessed from within the constructor, which means that any private or privileged function has access to them.

Since they are declared outside of the constructor, they do not have access to any of the private attributes, and as such, are not privileged; private methods can call private static methods, but not the other way around.

Page 59: Javascriptinobject orientedway-090512225827-phpapp02

59

var Book = (function() {var numOfBooks = 0; // Private static attributes.function checkIsbn(isbn) { // Private static method....}// Return the constructor.return function(newIsbn, newTitle, newAuthor) {

var isbn; // Private attributes.this.getIsbn = function() { // Privileged methods.

return isbn;};this.setIsbn = function(newIsbn) {

if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');isbn = newIsbn;

};

numOfBooks++; // Keep track of how many Books have been createdthis.setIsbn(newIsbn);

}})();Book.convertToTitleCase = function(inputString) { // Public static method....};Book.prototype = { // Public, non-privileged methods.

display: function() {...}

};

Page 60: Javascriptinobject orientedway-090512225827-phpapp02

60

A Short Summary

Private and Privileged members can only be made when an object is constructed.

Public members can be added at any time.

Having too many privileged methods can cause memory problems because new copies of all privileged methods are created for each instance.

In the public members pattern, all methods are created off of the prototype, which means there is only one copy of each in memory, no matter how many instances you create.

Page 61: Javascriptinobject orientedway-090512225827-phpapp02

61

Inheritance:The Employee Example

Page 62: Javascriptinobject orientedway-090512225827-phpapp02

62

Very Simple Implementation

Page 63: Javascriptinobject orientedway-090512225827-phpapp02

63

Object Hierarchy

Page 64: Javascriptinobject orientedway-090512225827-phpapp02

64

How does it work?

Suppose you create the mark object:var mark = new WorkerBee();

When JavaScript sees the new operator, it creates a new generic object and passes this new object as the value of the this keyword to the WorkerBee constructor function.

Then sets the value of WorkerBee.prototype to an object of Employee to setup prototype chain.

Page 65: Javascriptinobject orientedway-090512225827-phpapp02

65

Local versus Inherited Values

When you access an object property, JavaScript performs these steps:

1. Check to see if the value exists locally. If it does, return that value.

2. If there is not a local value, check the prototype chain.

3. If an object in the prototype chain has a value for the specified property, return that value.

4. If no such property is found, the object does not have the property.

Page 66: Javascriptinobject orientedway-090512225827-phpapp02

66

Does it work?

Suppose you create amy instance.var amy = new WorkerBee();

amy.name = “”;

amy.dept = “general”;

amy.projects = [];

Now, suppose you change the value of the name property in the prototype associated with Employee.Employee.prototype.name = “Unknown”;

Page 67: Javascriptinobject orientedway-090512225827-phpapp02

67

Does it work? (cont.)

If you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor’s prototype, not in the constructor function itself.

function Employee() {this.dept = “general”;

}Employee.prototype.name = “”;function WorkerBee() {

this.projects = [];}WorkerBee.prototype = new Employee();

amy = new WorkerBee();

Employee.prototype.name = “Unknown”;

Page 68: Javascriptinobject orientedway-090512225827-phpapp02

68

Adding Properties

In JavaScript, you can add properties to any object at run time.

To add a property that is specific to a single object, you assign a value to the object.mark.bonus = 3000;

Now, the mark object has a bonus property, but no other WorkerBee has this property.

Page 69: Javascriptinobject orientedway-090512225827-phpapp02

69

Adding Properties (cont.)

If you add a new property to an object that is being used as the prototype for a constructor function, you add that property to all objects that inherit properties from the prototype.Employee.prototype.specialty = “none”;

Page 70: Javascriptinobject orientedway-090512225827-phpapp02

70

Adding Properties (cont.)

Page 71: Javascriptinobject orientedway-090512225827-phpapp02

71

More Flexible Constructors

Page 72: Javascriptinobject orientedway-090512225827-phpapp02

72

More Flexible Constructors

Page 73: Javascriptinobject orientedway-090512225827-phpapp02

A Cleaner Approach

Another way of inheriting is by using the  .call/.apply methods. Below are equivalent:

Using the javascript .call method makes a cleaner implementation because the ".base" is not needed anymore.

Page 74: Javascriptinobject orientedway-090512225827-phpapp02

74

Don’t suppose it will work

Just because you have called the WorkerBee constructor from inside the Engineering constructor, you have set up inheritance appropriately for Engineer object. This is not the case.

Calling the WorkerBee constructor ensures that an Engineer object starts out with the properties specified in all constructor functions that are called.

If you later add properties to the Employee or WorkerBee prototypes, those properties are not inherited by the Engineer object.

Page 75: Javascriptinobject orientedway-090512225827-phpapp02

75

Don’t suppose it will work (cont.)

function Enginner(name, projs, mach) { WorkerBee.call(this, name, “engineering”, projs); this.match = mach || “”;

}var jane = new Engineer(“Doe, Jane”, [“navigator”, “javascript”], “belau”);Employee.prototype.specialty = “none”;

The jane object does not inherit the specialty property. You still need to explicitly set up the prototype to ensure dynamic inheritance.

Page 76: Javascriptinobject orientedway-090512225827-phpapp02

76

No Multiple Inheritance

JavaScript does not support multiple inheritance.

Because an object has a single associated prototype, JavaScript cannot dynamically inherit from more than one prototype chain.

In JavaScript, you can have a constructor function call more than one other constructor function within it.

Page 77: Javascriptinobject orientedway-090512225827-phpapp02

77

No Multiple Inheritance (cont.)

function Hobbyist(hobby) {

this.hobby = hobby || “scuba”;

}

function Engineer(name, projs, mach, hobby) {

WorkerBee.call(this, name, “engineering”, projs);

Hobbyist.call(this, hobby);

this.machine = mach || “”;

}

Engineer.prototype = new WorkerBee();

dennis = new Engineer(“Doe Dennis”, [“collabra”], “hugo”);

Page 78: Javascriptinobject orientedway-090512225827-phpapp02

78

No Multiple Inheritance (cont.)

Assume, you then add a property to the Hobbyist constructor’s prototype.Hobbyist.prototype.equipment = [“mask”, “fins”, “regulator”, “bcd”];

The dennis object does not inherit this new property.

Page 79: Javascriptinobject orientedway-090512225827-phpapp02

79

Patterns Summary

Publicfunction Constructor(…) {

this.membername = value;}

Constructor.prototype.membername = value;

Privatefunction Constructor(…) {

var that = this;

var membername = value;function membername(…) {…}

}

Page 80: Javascriptinobject orientedway-090512225827-phpapp02

80

Patterns Summary (cont.)

Privilegedfunction Constructor(…) {

this.membername = function(…) {…};}

Inheritancevar SuperClass = function(…) {

this.superclassmember = value;};var SubClass = function(…) {

SuperClass.call(this, params);this.subclassmember = value;

};SubClass.prototype = new SuperClass();

Page 81: Javascriptinobject orientedway-090512225827-phpapp02

81

Practical Closures

Page 82: Javascriptinobject orientedway-090512225827-phpapp02

82

Practical closures

A closure lets you associate some data (environment) with a function that operates on that data.

You can use a closure anywhere that you might normally use an object with only a single method.

Page 83: Javascriptinobject orientedway-090512225827-phpapp02

83

Example 1: Factory Method

Suppose, we wish to add to a page buttons that adjust the size of the page text.

function size12() {document.body.style.fontSize = “12px”;

}

function size14() {document.body.style.fontSize = “14px”;

}

function size16() {document.body.style.fontSize = “16px”;

}

Page 84: Javascriptinobject orientedway-090512225827-phpapp02

84

Example 1: Factory Method (cont.) Now, one could imagine that you would

want to generalize this notion of an “size function”, and you would not want to write dozens and dozens of size functions.function makeSizer(size) {

return function() { document.body.style.fontSize = size + “px”;}

}

var size12 = makeSize(12);var size14 = makeSize(14);var size16 = makeSize(16);

Page 85: Javascriptinobject orientedway-090512225827-phpapp02

85

Example 1: Factory Method (cont.)• We can attach them to buttons as

follows:

Page 86: Javascriptinobject orientedway-090512225827-phpapp02

86

Example 2: Emulating private methods with closures The shared environment is created in

the body of an anonymous function, which is executed as soon as it has been defined.

The environment contains two private items: a variable called privateCounter and a function called changeBy.

Neither of these private items can be accessed directly from outside the anonymous function.

Page 87: Javascriptinobject orientedway-090512225827-phpapp02

87

var Counter = (function() {var privateCounter = 0;function changeBy(val) { privateCounter += val;}return {

increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; }

}})();

alert(Counter.value()); //0Counter.increment();Counter.increment();alert(Counter.value()); //2Counter.decrement();alert(Counter.value()); //1

Page 88: Javascriptinobject orientedway-090512225827-phpapp02

88

Example 3: Emulating private static methods with closures See slide 58 and 59.

Page 89: Javascriptinobject orientedway-090512225827-phpapp02

89

Example 4: Creating closures in loops

Page 90: Javascriptinobject orientedway-090512225827-phpapp02

90

Explanation

The reason for this is the functions assigned to onfocus are closures; they consist of the function definition and the captured environment from the setupHelp function’s scope.

Three closures have been created, but each one shares the same single environment.

By the time the onfocus callbacks are executed, the loop has run its course and the item variable (shared by all three closures) has been left pointing to the last entry in the helpText list.

Page 91: Javascriptinobject orientedway-090512225827-phpapp02

91

Typical Solution

Page 92: Javascriptinobject orientedway-090512225827-phpapp02

Using Anonymous Functions to Induce the Scope// Iterate through each of the items

for ( var i = 0; i < helpText.length; i++ ) {

// Use a self-executed anonymous function to induce scope

(function(){

// Remember the value within this scope

var item = helpText[i];

// Bind a function to the element

document.getElementById(item).onfocus = function() {

// item refers to a parent variable

// scoped within the context of this for loop

document.getElementById(‘help’).innerHTML = item.help;

};

})();

}

Page 93: Javascriptinobject orientedway-090512225827-phpapp02

93

Example 5: setTimeout with Function References A common use for a closure is to provide

parameters for the execution of a function prior to the execution of that function.

The problem is that the function that passes to setTimeout cannot provide parameters.

However, code could call another function that returned a reference to an inner function object, with that inner function object being passed by reference to the setTimeout function. The parameters to be used for the execution of the inner function are passed with the call to the function that returns it.

Page 94: Javascriptinobject orientedway-090512225827-phpapp02

94

Example 5: setTimeout with Function References (cont.)function callLater(paramA, paramB, paramC) {

return function() {paramA[paramB] = paramC;

}};

var functRef = callLater(elStyle, “display”, “none”);setTimeout(functRef, 500);

Page 95: Javascriptinobject orientedway-090512225827-phpapp02

Example 6: Using Anonymous Functions to Hide Variables from the Global Scope// Create a new anonymous function, to use as a wrapper

(function(){

// The variable that would, normally, be global

var msg = "Thanks for visiting!";

// Binding a new function to a global object

window.onunload = function(){

// Which uses the 'hidden' variable

alert( msg );

};

// Close off the anonymous function and execute it

})();

Page 96: Javascriptinobject orientedway-090512225827-phpapp02

96

Example 7: Associating Functions with Object Instance Methods You want to associate different functions

to each event handler. Don’t put associateObjWithEvent() inside

the DhtmlObject constructor function. See Accidental Closures and Performance considerations for more details.

Page 97: Javascriptinobject orientedway-090512225827-phpapp02

function associateObjWithEvent(obj, methodName){

return function(e){

e = e || window.event;

return obj[methodName](e, this);

};

}

function DhtmlObject(elementId){

var el = getElementWithId(elementId);

if(el){

el.onclick = associateObjWithEvent(this, "doOnClick");

el.onmouseover = associateObjWithEvent(this, "doMouseOver");

el.onmouseout = associateObjWithEvent(this, "doMouseOut");

}

}

DhtmlObject.prototype.doOnClick = function(event, element){

... // doOnClick method body.

};

DhtmlObject.prototype.doMouseOver = function(event, element){

... // doMouseOver method body.

};

DhtmlObject.prototype.doMouseOut = function(event, element){

... // doMouseOut method body.

};

Page 98: Javascriptinobject orientedway-090512225827-phpapp02

98

Example 8: Encapsulating Related Functionality The array is going to act as a buffer for the output, but

defining it locally to the function will result in its re-creation on each execution of the function.

One approach might make the array a global variable so that it can be re-used without being re-created. But the effect is to render the code less manageable, as, if it is to be used elsewhere. It also makes the code less easy to integrate with other code because it pollutes the global namespace.

A Closure allows the buffer array to be associated (and neatly packaged) with the function that is dependent upon it and simultaneously keep the property name to which the buffer array as assigned out of the global namespace and free of the risk of name conflicts and accidental interactions.

Page 99: Javascriptinobject orientedway-090512225827-phpapp02

var getImgInPositionedDivHtml = (function(){

var buffAr = [

'<div id="', '', // index 1, DIV ID attribute

'" style="position:absolute;top:', '', // index 3, DIV top position

'px;left:', '', // index 5, DIV left position

'px;width:', '', // index 7, DIV width

'px;height:','', // index 9, DIV height

'px;overflow:hidden;\"><img src=\"', '', // index 11, IMG URL

'\" width=\"', '', // index 13, IMG width

'\" height=\"', '', // index 15, IMG height

'\" alt=\"', '', // index 17, IMG alt text

'\"><\/div>'

];

return function(url, id, width, height, top, left, altText){

buffAr[1] = id; buffAr[3] = top;

buffAr[5] = left;

buffAr[13] = (buffAr[7] = width);

buffAr[15] = (buffAr[9] = height);

buffAr[11] = url; buffAr[17] = altText;

return buffAr.join('');

}; //:End of inner function expression.

})();

Page 100: Javascriptinobject orientedway-090512225827-phpapp02

100

Example 8: Encapsulating Related Functionality The array is going to act as a buffer for the output, but

defining it locally to the function will result in its re-creation on each execution of the function.

One approach might make the array a global variable so that it can be re-used without being re-created. But the effect is to render the code less manageable. It also makes the code less easy to integrate with other code because it pollutes the global namespace.

A Closure allows the buffer array to be associated (and neatly packaged) with the function that is dependent upon it and simultaneously keep the property name to which the buffer array as assigned out of the global namespace and free of the risk of name conflicts and accidental interactions.

Page 101: Javascriptinobject orientedway-090512225827-phpapp02

Accidental Closures

Rendering any inner function accessible outside of the body of the function in which it was created will form a closure.

Accidentally creating closures can have harmful side effects as the following section on the IE memory leak problem describes.

A common situation is where inner functions are used is as event handlers for DOM elements.

Page 102: Javascriptinobject orientedway-090512225827-phpapp02

Accidental Closures (cont.)

var quantaty = 5;

function addGlobalQueryOnClick(linkRef){

if(linkRef){

linkRef.onclick = function(){

this.href += ('?quantaty='+escape(quantaty));

return true;

};

}

}

Whenever the addGlobalQueryOnClick function is called a new inner function is created (and a closure formed by its assignment).

From the efficiency point of view that would not be significant if the addGlobalQueryOnClick function was only called once or twice, but if the function was heavily employed many distinct function objects would be created (one for each evaluation of the inner function expression).

Page 103: Javascriptinobject orientedway-090512225827-phpapp02

Accidental Closures (cont.)

As the inner function in the first version is not being used to exploit the closures produced by its use, it would be more efficient not to use an inner function, and thus not repeat the process of creating many essentially identical function objects.

var quantaty = 5;function addGlobalQueryOnClick(linkRef){ if(linkRef){ linkRef.onclick = forAddQueryOnClick; }}function forAddQueryOnClick(){ this.href += ('?quantaty='+escape(quantaty)); return true;}

Page 104: Javascriptinobject orientedway-090512225827-phpapp02

104

References

Pro JavaScript Design Patterns JavaScript Definitive Guide 5th edition Pro JavaScript Techniques https://developer.mozilla.org/en/A_re-introduction_to_JavaScript https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/

Details_of_the_Object_Model https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/

Working_with_Closures http://www.jibbering.com/faq/faq_notes/closures.html http://en.wikipedia.org/wiki/JavaScript http://blogs.msdn.com/ericlippert/archive/

2003/09/17/53028.aspx http://msdn.microsoft.com/en-us/library/bb250448.aspx

Page 105: Javascriptinobject orientedway-090512225827-phpapp02

105

References (cont.)

http://blog.j15r.com/2005/06/another-word-or-two-on-memory-leaks.html

http://en.wikipedia.org/wiki/Closure_(computer_science) http://javascript.crockford.com/inheritance.html http://blog.j15r.com/2005/01/dhtml-leaks-like-sieve.html http://www.crockford.com/javascript/private.html http://www.quirksmode.org/blog/archives/2005/02/

javascript_memo.html http://vinaytech.wordpress.com/2009/02/24/

closuresandiecircular/ http://www.ibm.com/developerworks/web/library/wa-

memleak/ http://support.microsoft.com/kb/830555 http://vinaytech.wordpress.com/2009/02/24/

closuresandiecircular/