Knowing javascript

Basic JavaScript introduction:

1var foo = 123;
2function increment () {
3    foo += 1;
4}
5increment();
6log(foo);

Another way to write the function is to use the var-anonymous approach. Instead of begins the definition with function, we begins with a variable declaration that refer to an anonymous function. In the form, we can have bettor control on which scope the variable apply to.

1var increment = function() {
2    foo += 1;
3};

But these code still put two variables to the global scope.

The rule of thumb in javascript is to make as less global variables as possible.

Now we have two global variables, foo and increment. How we can make it 1 global variable? We can namespace it.

The code that wrap the variables into one object.

 1var counter = {
 2  foo: 123,
 3  increment: function() {
 4      this.foo += 1;
 5      log('new foo: ' + this.foo);
 6  }
 7}
 8log('foo: ' + counter.foo);
 9counter.increment()

Or you can edit the code here.

And the result

foo: 123
new foo: 124

One global variable. This sounds good. But do you know that we can make it zero global variable in some cases?

This requires another concept, the scope of a variable. The variable scope follows the function or it is attached to window if there is no function as its parent.

In JS, the variable scope follows the function.

Let’s test this statement with a simple experienment.

1var f = function() {
2  var foo = 123;
3  log('Inside : ' + foo);
4};
5f();
6log('Outside : ' + foo);

The foo in the outside is undefined.

So how we can apply this to our example code?

Approach 1: We get rid of the counter variable but introduced a now function reference run.

 1var run = function() {
 2  var counter = {
 3    foo: 123,
 4    increment: function() {
 5      this.foo += 1;
 6      log('new foo: ' + this.foo);
 7    }
 8  };
 9  log('foo: ' + counter.foo);
10  counter.increment();
11};
12run();

Approach 2: Then we can take away of the run and the code becomes a self-invoked snippet.

 1;(function() {
 2  var counter = {
 3    foo: 123,
 4    increment: function() {
 5      this.foo += 1;
 6      log('new foo: ' + this.foo);
 7    }
 8  };
 9  log('foo: ' + counter.foo);
10  counter.increment();
11})();

By the way, have you noted the semi-colon at the beginning and end? It is used to prevent wrong logic applied when concatenating JS file together.

Note: When creating a new variable, do you know the difference between foo = 123 and var foo = 123?

The foo = 123 version will directly make the foo a global variable regardless where function scope it is in. And the var foo = 123 follows the function-scope rule.

So, it 100% cases, we should not declare variable without the var.

What about we need several Counter instances?

 1;(function() {
 2  var Counter = function() {
 3    this.foo = 123;
 4  };
 5  Counter.prototype.increment = function() {
 6    this.foo += 1;
 7    log('new foo: ' + this.foo);
 8  };
 9
10  var counter = new Counter();
11  log('foo: ' + counter.foo);
12  counter.increment();
13})();

The prototype is the key concept in writing object-oriented JavaScript. When we use new to create object instance, only properties in prototype will be cloned. If you map the traditional class approach, any Counter.methods is class method and Counter.prototype.methods is instance method.

And in order to create inheritance, we assign the parent class as the prototype in the subclass. We call it prototype chain.

Here is the result logging the counter instance to console.

Prototype

Well, actually we get an even better approach.

 1;(function() {
 2  var Counter = (function(){
 3    function Counter() {
 4      this.foo = 123;
 5    };
 6    Counter.prototype.increment = function() {
 7      this.foo += 1;
 8      log('new foo: ' + this.foo);
 9    };
10    return Counter;
11  })();
12
13  var counter = new Counter();
14  log('foo: ' + counter.foo);
15  counter.increment();
16})();

Did I mention that JavaScript is difficult to master? You will find that you can do the same thing in many ways. And each approach may comes to some pros and cons. Some violate best practices. Some follow the practices.

Exercise

Can you code a component that starts at a user given value and it counts down every time you called its countDown method?

Want to test javascript quickly? You may consider using jsFiddle.

What’s next? We’re going to take a look at “Choosing javascript ui frameworks”.

overlaied image when clicked on thumbnail

Makzan | Mobile web app dev with phonegap | Table of Content