Dapeng Li

Hungry, foolish and passionate – yet another software developer.

Just Enough JavaScript – Prototype and Inheritance

leave a 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

Just Enough JavaScript – Variable Scope and Object

leave a comment

This is the first post on Just Enough JavaScript, we’ll cover variable scope and object.

Variable Scope 1

Global variables, local variables

In your program, the scope of a variable is the region within which that variable is valid.

Based on the scope, there are two types of variables in JavaScript: global variables and local variables. Global variables are accessible from everywhere in your code; local variables are only accessible within the function it’s defined.

// ex_1.1
// global_variables_local_variables

var global = "global";  // this is a global variable, visible in everywhere

function myFunc(param) {  // function argument has the same scope as local variable
	var local = "local";  // this is a local variable, visible in myFunc
}

Within a function, a local variable takes precedence over a global variable with the same name.

// ex_1.2
// local_variables_shadow_global_variables

var scope = "global";  // a global variable

function myFunc() {
	var scope = "local";  // scope variable will has the value "local" inside myFunc
	console.log(scope);  // "local"
}

myFunc();  // "local"
console.log(scope);  // "global"

Accessing a variable declared but not initialized with return undefined, accessing a variable not declared will cause a ReferenceError.

// ex_1.3
// variable_undefined

var variable = "global";
console.log(variable);  // "global"

function myFunc() {
	var mysteryVariable;  // declare variable, but doesn't initialize

	console.log(mysteryVariable);  // undefined
	console.log(anotherMysteryVariable);  // ReferenceError: anotherMysteryVariable is not defined
}

myFunc();

Only function scope, no block scope

Some other languages have block scope, where code inside curly braces has its own scope, JavaScript doesn’t have block scope.

The only way to create a scope in JavaScript is to define a function, JavaScript only has function scope.

Because of the lack of block scope, you should be aware of variable scopes when using curly braces.

// ex_1.4
// function_scope

function test(o) {
	var i = 0;  // i is defined throughout function

	if (typeof o === "object") {
		var j = 0;  // j is defined everywhere, not just block

		for (var k = 0; k < 10; k++) {  // k is defined everywhere, not just loop
			console.log(k);  // print numbers 0 through 9
		}

		console.log(k);  // k is still defined: prints 10
	}

	console.log(j);  // j is defined, but may not be initialized
}

In the example above, variable i, j and k are all in the same scope.

Hoisting

In example 1.4, it’s as if variable i, j and k were declared in the first line of function – being hoisted to the top of function. Just like this:

// ex_1.5
// function_scope_hoisting

function test(o) {
	var i = 0, j, k; // declaration of j and k are hoisted to the beginning of function

	if (typeof o === "object") {
		j = 0;

		for (k = 0; k < 10; k++) {
			console.log(k);
		}

		console.log(k);
	}

	console.log(j);
}

Another effect of hoisting is sometimes a variable can be accessed before it’s declared, consider the following example.

// ex_1.6
// hoisting_puzzle

var scope = "global";

function f() {
	console.log(scope); // Prints "undefined", not "global"
	var scope = "local"; // Variable initialized here, but defined everywhere
	console.log(scope); // Prints "local"
}

f();

Although variable scope was declared in line 8, because of the hoisting effect, it can be accessed in line 7. It’s as if it’s declared like this:

// ex_1.7
// hoisting_puzzle2

function f() {
	var scope; // Local variable is declared at the top of the function
	console.log(scope); // It exists here, but still has "undefined" value
	scope = "local"; // Now we initialize it and give it a value
	console.log(scope); // And here it has the value we expect
}

Because JavaScript doesn’t have block scope, it’s a good practice to declare all of the variables used in a function at the top of the function body. Just like the code in example 1.5.

Use var keyword

JavaScript is a dynamic typed language, so you don’t specify the type of your variable in declaration, you can just use the var keyword.

It’s a good practice to always use the var keyword in variable declaration, if you don’t specify the var keyword, that variable will be declared in global scope.

// ex_1.8
// var_keyword

scope = "global";  // Declare a global variable, even without var.

function checkscope2() {
	scope = "local";  // Oops! We just changed the global variable.
	myscope = "local";  // This implicitly declares a new global variable.
	return [scope, myscope]; // Return two values.
}

checkscope2();  // => ["local", "local"]: has side effects!
console.log(scope);  // "local": global variable has changed.
console.log(myscope);  // "local": global namespace cluttered up.

Lexical scoping

In JavaScript, a variable is visible throughout the function in which it’s declared (thus the name “function scope”), and also within any functions nested within that function.

JavaScript is a lexically scoped language, means 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.

These two characteristics will lead to an important concept named closure, when you’re considering a function and the environment under which that function was invoked. We will visit closure in next post on functions.

Object 2

In JavaScript, objects are mutable keyed collections. 3

Creating new objects – Object Literal

Create JavaScript objects with the object literal syntax: a pair of curly braces surrounding zero or more name/value pairs.

// ex_1.9
// object_literal

var empty = {};  // An object with no properties
var point = { x: 0, y: 0 };  // Two properties
var point2 = { x: point.x, y: point.y + 1 };  // More complex values

var book = {
	"main title": "JavaScript",  // Property names include spaces,
	'sub-title': "The Definitive Guide",  // and hyphens, so use string literals
	"for": "all audiences",  // for is a reserved word, so quote
	author: {  // The value of this property is
		firstname: "David",  // itself an object. Note that
		surname: "Flanagan"  // these property names are unquoted.
	}
};

Creating new objects – with Constructor

Use new operator to invoke a function to create an object. That function is usually called constructor, code in the constructor function will initialize the newly created object. Constructor also determines the prototype of the newly created object, we’ll review prototype in a later post on prototype and inheritance.

// ex_1.10
// constructor

var o = new Object();  // Create an empty object: same as {}.
var a = new Array();  // Create an empty array: same as [].

function MyType() {  // MyType is a constructor
	// code to initialize new object
}

var myInstance = new MyType();  // create an instance of MyType

Retrieval/Update/Delete

Values in an object can be retrieved with the [] suffix. Like retrieving a value in a hash. If the key is a legal JavaScript name and not a reserved word, then we can use the . notation.

Accessing a non-existent property of object will return undefined.

// ex_1.11
// object_properties

var book = {
	"main title": "JavaScript",
	'sub-title': "The Definitive Guide",
	"for": "all audiences",
	author: {
		firstname: "David",
		surname: "Flanagan"
	}
};

// Get
var name = book.author.surname;  // Get the "surname" property of the author property.
var title = book["main title"];  // Get the "main title" property of the book.
var unknown = book.mystery_chapter;  // accessing a property not exist will return undefined

// Update
book.edition = 6;  // Create an "edition" property of book.
book["main title"] = "ECMAScript";  // Set the "main title" property.

// Delete
delete book.author;  // The book object now has no author property.
delete book["main title"];  // Now it doesn't have "main title", either.

Add new properties/functions

Setting a value to a property doesn’t exist in an object will cause that property be created.

// ex_1.12
// object_properties_augment

var obj = {};  // create a new object

obj.newProperty = 15;  // create a new property named newProperty

console.log(obj.newProperty);  // 15

Equality test 4

Douglas Crockford recommends using === and !== operators for equality test. If the values being compared are of the same type and same value, === will return true and !== will return false.

Avoid using their “evil twins” (== and !=), which will try to coerce when the values being compared are of different types.

OK, that’s a quick tour of Variable Scope and Object in JavaScript. We’ll see functions upcoming next.


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

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

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

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

Written by Dapeng

May 15th, 2012 at 9:38 pm

Posted in Programming

Tagged with

Just Enough JavaScript – Introduction

one comment

For years I’ve been finding execuses for not learning JavaScript, until I realize that whether you love or hate JavaScript, it can’t be ignored. It’s the language of the web.

During my journey of learning JavaScript this month, I would like to write some notes about this language (a series of posts, more on that later). Preparing these notes helped me understanding JavaScript, and hopeful it might help other developers who are new to JavaScript, or if you’re like me, from a C-based object-oriented programming language.

Just enough

The title of this post is “Just Enough JavaScript”, but why “just enough”? How much is “just enough”?

Here’s the thing: I want to be able to read and write JavaScript code confidently, but not planning to be a JavaScript ninja.

A new language called CoffeeScript got popular since its inception in 2009. CoffeeScript is a small language with Ruby-like syntaxes and compiles into JavaScript. CoffeeScript is simple, elegant, and “it’s just JavaScript”.

I set the scope/goal of learning JavaScript (call it iteration #1) as this:

Learn “just enough” JavaScript so that I can understand the JavaScript compiled by CoffeeScript.

I choose that scope and learn CoffeeScript along the way based on the following considerations:

  • Developers use CoffeeScript for production projects, which means CoffeeScript and the JavaScript it compiles to will cover enough features in JavaScript to get your work done.
  • To use CoffeeScript effectively one should understand the compiled JavaScript code from the CoffeeScript code. Abstraction is great, but abstraction leaks.
  • JavaScript has some quirks, the JavaScript code compiled from CoffeeScript are idiomatic JavaScript – means they’re good JavaScript code. One can learn to write JavaScript from reading those good code.
  • There’s a very small learning curve for CoffeeScript so it’s not a big commitment. Spend some time learning CoffeeScript and enjoy the productivity boost; even if CoffeeScript is not relevant in the future, what I’ve got is knowledge on JavaScript. Either way, that sounds like a good investment to me.

Plan

At this moment I’m planning to write three posts, most of them are from the books and resources I found helpful, the topics are:

  1. Variable Scope and Object
  2. Function
  3. Prototype and Inheritance

This series will not cover all language features of JavaScript used by CoffeeScript, but should be a good start.

The latest version of CoffeeScript as of this writing is 1.3.2.

A note on books and resources:

I started with JavaScript: The Good Parts 1 and about 1/3 into the book I realized it’s not a book for developers who just started learning JavaScript; next I followed Eloquent JavaScript 2 as a tutorial, some documentations on MDN; then I found JavaScript: The Definitive Guide 3 to be a good reference and detailed explanation on many concepts; at that moment revisiting JavaScript: The Good Parts made more sense.

PragProg’s CoffeeScript book 4 is the one I followed for learning CoffeeScript, and of course, CoffeeScript.org.

A note on the content I borrowed:

When I was trying to assemble the content for the posts based on various resources I read, I end up referring to David Flanagan’s book JavaScript: The Definitive Guide, and what you will see is just a rehash of some sections from David’s book.

I felt bad about this blatant copying approach, on the other hand I felt equally bad if I tried to mix my words with excerpts from the book, or some my own examples only cosmetically different. That is a book of quality: concepts are well explained, examples are concise and clear. If you’re looking for a good JavaScript resource, I highly recommend purchasing JavaScript: The Definitive Guide.

All examples are updated to conform more with Douglas Crockford’s JSLint recommendations, except the ones illustrating language features, such as variable hoisting and closure in a loop.

OK, the ground is set, let’s begin. JavaScript!


1. JavaScript: The Good Parts by Douglas Crockford, Amazon Link

2. Eloquent JavaScript: A Modern Introduction to Programming by Marijn Haverbeke, Amazon Link

3. JavaScript: The Definitive Guide, 6th Edition by David Flanagan, Amazon Link

4. CoffeeScript: Accelerated JavaScript Development by Trevor Burnham, PragProg Link

Written by Dapeng

May 15th, 2012 at 8:27 pm

Posted in Programming

Tagged with