Dapeng Li

Hungry, foolish and passionate – yet another software developer.

Archive for May, 2012

Just Enough JavaScript – Prototype and Inheritance

one comment

This is the third and last post on Just Enough JavaScript, we’ll cover Prototye and Inheritance in JavaScript.

Prototype

Prototype: an early sample or model built to test a concept or process or to act as a thing to be replicated or learned from. (From Wikipedia)

Classical vs. Prototypal

In a classical programming language, you specify the structure and behavior of a type of objects in the definition of a class, by instantiating new objects of that class (usually with the new keyword to invoke the constructor defined in the class), you get objects sharing the same behavior but with inner states of their own. You can also specify a class to inherit from another class, constructing a class hierarchy, child class will has access to state and behavior of parent class. When a property is accessed from an object, it will be first looked for in the class of that object; if it’s not there, it will be looked for in the parent class of that object – the property will be looked up in the class hierarchy.

JavaScript takes a different approach supporting the code reuse and inheritance parts, it’s prototypal. Although JavaScript has the new keyword and the concept of constructor, there is no class in the language. In JavaScript, you create a new object, specify its state and behavior (properties); then use that object as a prototype, you create new objects just like that one. When a property is accessed from an object, it will be first looked for in the object itself; if it’s not there, it will be looked for in the prototype of that object – the property will be looked up in the prototype chain. Without an abstraction of class, the prototypal approach is actually simpler.

What’s the difference between classical and prototypal?

In my opinion, the goals of both approaches are the same – to achieve code reuse and a mechanism for expressing inheritance hierarchy. When programming in an object-oriented programming language (classical and prototypal are just different paradigms implementing object-orientation), you rarely have an object of its own kind, instead you create objects of the same kind (with different inner states, but similar behaviors); from generalization to specialization, you need an inheritance hierarchy.

The prototypal way

Here’s one flow to create a new object based on a prototype in JavaScript.

  1. Create an object p, which will be used as prototype
  2. Create a function to create new objects, which will set the prototype of newly created object to p
  3. Use the function in #2 to create new objects

#1 is easy to achieve, we can create new object with object literals, but what about #2 and #3?

Fortunately JavaScript has language features for #2 and #3, the bad news is those features are a little bit confusing.

Remember constructor (discussed in last post on function)? It’s used for creating new objects, that’s for #3. It turns out constructor also has a property called prototype, when you set an object (in our case, p) to the prototype property of a constructor, new objects created with that constructor will have their prototype set to be the object p.

// ex_3.1
// prototypal_way_new_object

var p, Ctor, obj1, obj2;

p = {  // Our prototype object
	name: "p"
};

Ctor = function () {  // Constructor
	this.greeting = function () {
		return "Hello " + this.name;
	};
};

Ctor.prototype = p;  // Set prototype property of Ctor to be p

obj1 = new Ctor();
obj1.name = "obj1";
console.log(obj1.greeting());  // Hello obj1

obj2 = new Ctor();
console.log(obj2.greeting());  // Hello p

If you update the prototype property of constructor (not replacing it), all objects created with that constructor will take effect immediately. Prototype chain is “live”, as in the following example.

// ex_3.2
// prototypal_way_change_existing_object_augment_prototype

var p, Ctor, obj, obj2;

p = {  // Our prototype object
	name: "p"
};

Ctor = function () {  // Constructor
	this.greeting = function () {
		return "Hello " + this.name;
	};
};

Ctor.prototype = p;  // Set prototype property of Ctor to be p

obj = new Ctor();
console.log(obj.greeting());  // Hello p

Ctor.prototype.age = 10;  // Update (augment) the prototype object

Ctor.prototype.howOld = function () {
	return this.age + " years old";
};

p.goodbye = function () {  // Or update prototype object directly
	return "Bye " + this.name;
};

console.log(obj.greeting());  // Hello p
console.log(obj.howOld());  // 10 years old
console.log(obj.goodbye());  // Bye p

obj2 = new Ctor();
console.log(obj2.greeting());  // Hello p
console.log(obj2.howOld());  // 10 years old
console.log(obj2.goodbye());  // Bye p

However, if you replace the prototype property of constructor, objects created after that will use the new prototype, existing objects will not. Consider this example:

// ex_3.3
// prototypal_way_change_existing_object_replace_prototype

var p, Ctor, p2, obj, obj2;

p = {  // Our prototype object
	name: "p"
};

Ctor = function () {  // Constructor
	this.greeting = function () {
		return "Hello " + this.name;
	};
};

p2 = {
	age: 10,
	howOld: function () {
		return this.age + " years old";
	}
};

Ctor.prototype = p;  // Set prototype property of Ctor to be p

obj = new Ctor();
console.log(obj.greeting());  // Hello p

Ctor.prototype = p2;  // Change the value of prototype property of Ctor to be p2

obj2 = new Ctor();
console.log(obj2.howOld());  // 10 years old

console.log(obj.howOld());  // Uncaught TypeError: Object #<Object> has no method 'howOld'

Here’s the confusing part: the constructor (it’s a function object) has its own prototype. The prototype of constructor has nothing to do with the prototype property of the constructor, the former is part of the prototype chain of the constructor object, the latter points to an object used as prototype for new objects created with the constructor.

Please take a moment to read this post on Understanding JavaScript Prototypes from Angus Croll, it sheds more light on this concept, and the remaining of this post will depend some contents not covered here (such as the [[prototype]] property), but they’re well explained in Angus’ post.

Here’s a diagram showing the relationship of constructor and object, simplified from our ex 3.1.

Prototype

One pseudoclassical way

Here’s a quote from Douglas Crockford 1:

JavaScript itself is not confident in its prototypal nature, so it offers an object-making syntax that is reminiscent of the classical languages. Few classical programmers found prototypal inheritance to be acceptable, and classically inspired syntax obscures the language’s true prototypal nature. It is the worst of both worlds.

Maybe because many developers are more familiar with the classical syntax, there are a lot of ways to emulate class in JavaScript.

Here’s the pseudoclassical code generated by CoffeeScript (line breaks added/removed for readability by me), the CoffeeScript code is class B extends A.

The goal of the code in the example below is to create a class B, which inherits from class A. Objects of class B will have access to properties of both B and A.

The implementation in the code generated by CoffeeScript is to update the prototype chain of constructor B: set the prototype of the object referenced by prototype property of constructor B to be the same as the object referenced by prototype property of constructor A.

The __extends() function below does that job, it accepts two constructor functions as arguments.

// ex_3.4
// pseudoclassical_CoffeeScript_class_B_extends_class_A

var B,
	__hasProp = {}.hasOwnProperty,
	__extends = function(child, parent) {
		for (var key in parent) {
			if (__hasProp.call(parent, key))
				child[key] = parent[key];
		}

		function ctor() { this.constructor = child; }

		ctor.prototype = parent.prototype;

		child.prototype = new ctor();

		child.__super__ = parent.prototype;

		return child;
	};

B = (function(_super) {
	__extends(B, _super);

	function B() {
		return B.__super__.constructor.apply(this, arguments);
	}

	return B;
})(A);

Here is the diagram showing the relationships between objects in ex 3.4, before the effect of __extends() function.

Inheritance before

Here is the diagram showing the relationships between objects in ex 3.4, after the effect of __extends() function.

Inheritance after

There’re many more patterns for inheritance, but I’m fine to stop here.

Final Thoughts

This post concludes our short journey with JavaScript.

Someone said JavaScript is perhaps the most widely used and most reviled programming language on the modern Web.

It’s interesting to learn about how Brendan Eich created the language with a tight deadline and other constraints. 2

I also realized that there are more factors than technology have impact on the evolving of a programming language such as JavaScript. (You can Google for “ECMAScript 4 Oslo”)

The good news is we’ll see more features be added to JavaScript, and developers will have better options to build a more beautiful web.


1. More details from page 29 in the book JavaScript: The Good Parts by Douglas Crockford, Amazon Link
2. More details from page 133 in the book Coders at Work: Reflections on the Craft of Programming by Peter Seibel, Amazon Link

Written by Dapeng

May 17th, 2012 at 8:12 pm

Posted in Programming

Tagged with

Just Enough JavaScript – Function

leave a comment

This is the second post on Just Enough JavaScript, we’ll cover function in JavaScript.

Function

JavaScript functions are objects, so they can be treated like other objects: they can be assigned to variables, assigned to properties of an object (or a function), passed to another funciton as arguments, or returned from a function.

Declaration

  • Function can be declared in a statement. This Function Decalartion Statement syntax should be familiar.
// ex_2.1
// function_declaration_1

function f(x) {
	return x + 1;
}
  • Function can also be declared in an expression. In this Function Definition Expression way you declare an anonymous function (or with a name if it’s meant to be called recursively) and assign it to a variable.
// ex_2.2
// function_declaration_2

var f = function(x) {
	return x + 1;
}

The statement way (ex 2.1) is just a shorthand for the expression way (ex 2.2), Douglas Crockford recommends the latter because it better conveys the notion that a function value was assigned to a variable. 1

Function declared in the statement way (ex 2.1) can be invoked before or after the declaration; function declared in the expression way (ex 2.2) can only be invoked after its declaration.

Invocation Context (this) 2

To invoke a function in code, specify the function name, open parenthesis, a list of arguments and close parenthesis.

JavaScript doesn’t perform checking on type or number of arguments when invoking a function, additional arguments will be ignored, and undefined will be placed for missing arguments.

There are four patterns for invoking a function, which will determine what this keyword means inside the function.

Method Invocation Pattern

When a function is stored as a property of an object, it is called a method. When a method is invoked (using . notation or [] expression), this is bound to that object.

// ex_2.3
// method_invocation_pattern

var calculator = {  // An object literal
	operand1: 1,
	operand2: 1,

	add: function () {
		// Note the use of the this keyword to refer to this object.
		this.result = this.operand1 + this.operand2;
	}
};

calculator.add();  // A method invocation to compute 1+1.
console.log(calculator.result);  // 2

Invoking a function on an object in this pattern conveys the intent that the method operates on the object.

Function Invocation Pattern

When a function is not the property of an object, then it is invoked as a function. When a function is invoked with this pattern, this is bound to the global object. As Douglas Crockford said, it was a mistake of the language design – this should bound to the this variable of the outer function.

// ex_2.4
// function_invocation_pattern

var foo, obj;

foo = function () {
	this.bar = 123;
};

foo();  // invoke using Function Invocation Pattern, this keyword bounds to global

console.log(bar);  // 123

obj = {
	bar: "Inside obj",
	my_foo: foo
};

obj.my_foo();  // invoke using Method Invocation Pattern, this keyword bounds to obj

console.log(obj.bar);  // 123

Be careful when invoking methods in an object, when you invoke other functions defined in the object from a method, this keyword will not bound to the same object (instead, this bounds to global). A workaround is to store the object context as a local variable, and use that variable instead of this. It’s better explained in an example:

// ex_2.5
// method_invocation_pattern2

var o = {  // An object o.
	m: function () {  // Method m of the object.
		var self = this;  // Save the this value in a variable.

		console.log(this === o);  // Prints "true": this is the object o.

		f();  // Now call the helper function f().

		function f() {  // A nested function f
			console.log(this === o);  // "false": this is global or undefined
			console.log(self === o);  // "true": self is the outer this value.
		}
	}
};

o.m();  // Invoke the method m on the object o.

Constructor Invocation Pattern

When a function is intended to be used for initializing new objects, it’s called constructor. Constructors should be called with the new keyword, when a constructor is invoked with the new keyword, this keyword inside the constructor is bound to the newly created object (which will be initialized by the code in the constructor).

The bad news is that there’s no difference between a function and a constructor from syntax perspective, if a constructor was invoked without the new keyword, bad things can happen – properties which were meant to be inside an object were attached to global. So it’s a convention to capitalize the first letter of the name of constructor.

// ex_2.6
// constructor_invocation_pattern

var MyType, myObj;

MyType = function () {  // MyType is a constructor
	this.value = "foo";
};

myObj = new MyType();  // invoke using Constructor Invocation Pattern, this keyword bounds to myObj

myObj.get_foo = function () {  // assign a function to a property of myObj
	return this.value;
};

console.log(myObj.get_foo());  // foo

We’ll revisit constructor in our next post on Prototype and Inheritance.

Apply Invocation Pattern (Indirect Invocation)

You can specify this by invoking the call() or apply() methods on a function.

The first argument passed to call() or apply() will be the context when invoking the function, and becomes the this keyword inside the function.

Additional arguments passed to call() after the first invocation context argument will be passed to the function that is invoked.

apply() method accepts the second argument as an array.

// ex_2.7
// apply_invocation_pattern

var MyType, myObj, anotherObj, result, result2;

MyType = function () {
	this.value = "foo";
};

myObj = new MyType();  // create a new object using MyType as constructor

anotherObj = { value: "bar" };  // create another object using object literal

myObj.appendToValue = function (suffix) {  // assign a function to a property of myObj
	return this.value + suffix;
};

result = myObj.appendToValue.call(anotherObj, "beque");  // call takes additional arguments for the method to invoke

result2 = myObj.appendToValue.apply(anotherObj, ["beque"]);  // apply takes the second argument as an array

console.log(result);  // barbeque

console.log(result2);  // barbeque

Namespace

All JavaScript objects not inside a function are bound to the global context, so it’s a common practice to create a function “wraps” your code, acting like a namespace. You need to invoke that wrapper function after declaration.

// ex_2.8
// namespace

var myModule = function () {
	// Module code goes here.
	// Any variables used by the module are local to this function
	// instead of cluttering up the global namespace.
};

myModule(); // But don't forget to invoke the function!

It’s more idiomatic to declare an anonymous function and invoke it immediately after declaration.

// ex_2.9
// namespace_IIFE

(function () {  // Create an IIFE (Immediately-Invoked Function Expression) as namespace
	// Module code goes here.
}());

window.foo = (function () {  // Attach another IIFE to global, code in other files can access it
	// Code for another module
}());

There’s a name for the immediately invoked function: IIFE (Immediately-Invoked Function Expression). To know more about IIFE – the name, the syntax (why parentheses around anonymous function are needed, why you should still use parentheses around anonymous function when assigning IIFE to a variable), please read this post on IIFE from Ben Alman.

You can attach your IIFE to global object (window or global) so code in other files can access your code in IIFE, as we did in ex 2.9.

Closure

Concept

Let’s revisit the concept of lexical scoping (introduced in Variable Scope section from last post): functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked.

Also, a variable is visible throughout the function in which it’s declared, and also within any functions nested within that function.

Since functions are objects, function object can have properties which are functions. Consider this example:

// ex_2.10
// closure

var getValue = (function () {
	var value = "foo";

	return function () {
		return value;  // this function has access to variable value of outer function when it's declared
	};
}());  // IIFE (Immediately-Invoked Function Expression)

console.log(getValue());  // foo?

On line 4, an anonymous function is invoked immediately after it’s declared, the return value is a function, and assigned to an object named getValue.

On line 12, the anonymous function on line 4 had returned so local variables in that anonymous function should be out of scope. However, getValue object points to a function which has access to the local variable value when that function was declared (line 7, because nested function has access to local variables declared in parent functions). What will happen if the function stored in getValue got invoked?

Here comes the concept of closure: it’s the combination of a function object and a scope (a set of variable bindings) in which the function’s variables are resolved.

In our example, when the function on line 7 was declared it had variable value in scope, so the variable value will always in scope to that function. It’s as if function “closed over” all variables in scope when it was declared.

So the function value stored in variable getValue has access to the variable value when it’s invoked. The output of last example is “foo”.

If you’re confused about the concept of closure, I recommend reading the closure section of the book JavaScript: The Definitive Guide 3, it’s very well explained there and with some good examples.

Encapsulation

Closures can be used for encapsulation, as in this example:

// ex_2.11
// closure_encapsulation

var counter, c, d;

counter = function () {
	var n = 0;

	return {  // returns an object literal encapsulating access to variable n
		count: function () { return n++; },
		reset: function () { n = 0; }
	};
};

// Create two counters
c = counter();
d = counter();

c.count();  // => 0
d.count();  // => 0: they count independently

c.reset();  // reset() and count() methods share state

c.count();  // => 0: because we reset c
d.count();  // => 1: d was not reset

The returned object literal has two functions count and reset, those two functions are the only way to access variable n.

Another thing to note from last example is that object c and d has inner states independent from each other.

Closure with locked variables

Be careful when returning functions from a loop:

// ex_2.12
// closure_lost_context

var constructFunctions, functions;

// Return an array of functions that return the values 0-9
constructFunctions = function () {
	var funcs = [], i;

	for (i = 0; i < 10; i++) {
		funcs[i] = function () {
			return i;  // encapsulate i in each function created
		};
	}

	return funcs;
};

functions = constructFunctions();
console.log(functions[5]());  // What does this return?

In the example above, each function in functions array has access to variable i, invoking each function will cause the value of i to be returned. However, when the funcs array is returned, the for loop had ended, the value of i is 10, so each closure created in funcs array will return the “current” value of i, which 10.

A workaround is to lock the variables in each iteration in a closure:

// ex_2.13
// closure_lock

var constructFunctions, functions, i;

// Return an array of functions that return the values 0-9
constructFunctions = function () {
	var funcs = [], returnValueFunc;

	returnValueFunc = function (value) {
		return function () {
			return value;
		};
	};

	for (i = 0; i < 10; i++) {
		funcs[i] = returnValueFunc(i);
	}

	return funcs;
};

functions = constructFunctions();
console.log(functions[5]());  // 5

Or use an anonymous function instead of named function as closure:

// ex_2.14
// closure_lock2

var constructFunctions, functions, i;

// Return an array of functions that return the values 0-9
constructFunctions = function () {
	var funcs = [];

	for (i = 0; i < 10; i++) {
		funcs[i] = (function (value) {  // wrap the function in an IIFE, lock the variable i
			return function () {
				return value;
			};
		}(i));
	}

	return funcs;
};

functions = constructFunctions();
console.log(functions[5]());  // 5

You can also lock the variables immediately with a closure when entering a loop:

// ex_2.15
// closure_lock3

var constructFunctions, functions, i;

// Return an array of functions that return the values 0-9
constructFunctions = function () {
	var funcs = [];

	for (i = 0; i < 10; i++) {
		(function (lockedIndex) {  // wrap code of each iteration in a closure, lock variables
			funcs[lockedIndex] = function () {
				return lockedIndex;
			};
		}(i));
	}

	return funcs;
};

functions = constructFunctions();
console.log(functions[5]());  // 5

I read about this trick from the IIFE post above, personally I feel it’s more readable this way.

Functional Programming 4

Because functions are objects in JavaScript, we can manipulate functions with functions.

ForEach

In the following example, an array and a function action() are passed as arguments to a function forEach(), the action() function will be invoked iteratively, each item in the array as argument is passed to action as argument.

// ex_2.16
// functional_foreach

var print, forEach, i;

print = function (value) {
	console.log(value);
};

forEach = function (array, action) {  // accepts second argument as a function
	for (i = 0; i < array.length; i++) {
		action(array[i]);
	}
};

forEach(["a", "b", "c"], print);

We can create other helper functions using the forEach() function in last example, here’s a function returns the sum of all items in an array (assuming all items are numbers):

// ex_2.17
// functional_sum

var forEach, i, sum, result;

forEach = function (array, action) {
	for (i = 0; i < array.length; i++) {
		action(array[i]);
	}
};

sum = function (numbers) {
	var total = 0;

	forEach(numbers, function (item) {
		total += item;
	});

	return total;
};

result = sum([1, 2, 3]);

console.log(result);  // 6

Map

Let’s try creating another helper function called map(), this function will accept an array, and an action will be performed on each item in the array, result after each processing will be pushed into a new array, finally the new array will be returned. It’s much simpler to express it in code:

// ex_2.18
// functional_map

var map, i, doubled;

map = function (array, action) {
	var newArray = [];

	for (i = 0; i < array.length; i++) {
		newArray.push(action(array[i]));
	}

	return newArray;
};

doubled = map([1, 2, 3], function (value) {
	return value * 2;
});

console.log(doubled);  // [2, 4, 6]

Reduce

Let’s create a last helper function called reduce(), which will accept an array, an initial value, and an action function. reduce() will process each item in the array with the action function, and return the accumulate result of each processing.

// ex_2.19
// functional_reduce

var reduce, i, sum, multiply, result, result2;

reduce = function (array, initial, action) {
	var accumulated = initial;

	for (i = 0; i < array.length; i++) {
		accumulated = action(accumulated, array[i]);
	}

	return accumulated;
};

sum = function (numbers) {
	return reduce(numbers, 0, function (accu, item) {
		return accu + item;
	});
};

multiply = function (numbers) {
	return reduce(numbers, 1, function (accu, item) {
		return accu * item;
	});
};

result = sum([1, 2, 3, 4]);  // 10
result2 = multiply([1, 2, 3, 4]);  // 24

console.log(result);
console.log(result2);

This concludes our review of functions in JavaScript, in next post we’ll see a prototypal way of inheritance.


1. More details from page 113 in the book JavaScript: The Good Parts by Douglas Crockford, Amazon Link

2. More details from page 27 in the book JavaScript: The Good Parts by Douglas Crockford, Amazon Link

3. More details from page 180 in the book JavaScript: The Definitive Guide, 6th Edition by David Flanagan, Amazon Link

4. More details from page 71 in the book Eloquent JavaScript: A Modern Introduction to Programming by Marijn Haverbeke, Amazon Link

Written by Dapeng

May 16th, 2012 at 7:46 pm

Posted in Programming

Tagged with