Advanced JavaScript


Recently I had the chance to see how deep the rabbit-hole goes when it comes to JavaScript.
Since my project should not involve any JavaScript thirdparties. I had to be creative
and sometimes yeah you're not going to believe it, I even had to google about it.
When we are talking about JavaScript the pain is even bigger because we have to be able to write
a cross browser code. In that point almost any average sane developer will pull out his best colorful
nose hairs.
I'm not going to cover the entire JavaScript language - this is not the case, I'm not writing a book.
I'm just going to put on the table some areas which are not trivial to the common JavaScript developer.

Agenda:

  •    Intro

  •    Data Object

  •    Function Constructor

  •    Namespaces & Closure

  •    Prototype

  •    Custom Event

  •    AOP

  •    Listener override

  •    CSS

  •    Native AJAX

  •    Canvas

  •    Misc

 

Intro:
JavaScript is a simple scripting language and yet complex and powerful language for nontrivial tasks.
JavaScript was originally developed by Brendan Eich of Netscape under the name Mocha,
later changed to LiveScript, and finally renamed to JavaScript.
Although Java and JavaScript has syntatic resemblance and they both provides executable content
in web browsers, JavaScript is not Java. The similarity of names is purely a marketing ploy by Netscape and Sun.

ECMAScript is a scripting language, standardized by Ecma International. It supported in many applications,
especially web browsers, where it is commonly called JavaScript.
Dialects sometimes include extensions to the language, or to the standard library and related APIs such as the W3C-specified DOM.
This means that applications written in one dialect may be incompatible with another,
unless they are written to use only a common subset of supported features and APIs.


Dialects of ECMAScript:

  •   Google Chrome, the V8 engine     JavaScript    

  •   Mozilla Firefox, the Gecko layout engine, SpiderMonkey, and Rhino 6 - JavaScript 1.8

  •   Internet Explorer, the Trident layout engine - JScript 5.7    

  •   Opera - ECMAScript with some JavaScript 1.5 and JScript extensions

  •   KHTML layout engine, KDE's Konqueror, and Apple's Safari7 - JavaScript 1.5 1    

  •   Appweb Web Server, Samba 4 - Ejscript 0.9.5

  •   Microsoft .NET Framework - JScript .NET 8.0    

  •   Adobe Flash and Adobe Flex - ActionScript 3    

  •   Adobe Acrobat - JavaScript 1.5 1

  •   OpenLaszlo Platform - JavaScript 1.4 1

  •   CriScript, JScript for game platforms - CriScript 0.9.0

  •  

Note: The following items will include examples which most of them cross platform solutions.

Data Object:
Before we are going to dive deep inside JS, lets learn a thing or two.
in JS Data object can be achived in several ways:
We can use JS Object like a map.

var foo = new Object();
foo['foo'] = 'foo';

Or we can use an Array object:
var foo = new Array();
foo['foo'] = 'foo';
foo[0] = 'foo';

for (var item in foo) {
    alert(foo[item]);
}


Just keep in mind that when you are using key values as numbers
it get mixed with the strings keys.
We can use a structure like in the followi:

var foo = {
    foo:'foo',
    fooArray: [1, 2, 3]
};
alert(foo.foo + " - " + foo.fooArray[0]);


we can also instantiate a function and use it as a Class:

function Foo(foo) {
    this.foo = foo;
    this.fooFun = function(){/* code in here */};
}
var fooInstance = new Foo('foo');
alert(fooInstance.foo);


In this example we can see how can we use part of the above examples to our advantage.

function Foo(x, y) {
    this.x = x;
    this.y = y

    this.calc = function() {
        return { sum:(this.x + this.y),
             mult:(this.x * this.y),
             sub:(this.x - this.y) }
    }
}

var fooInstance = new Foo(5, 6);
alert(fooInstance.calc().sum);
fooInstance.x = 7;
alert(fooInstance.calc().sum);



Function Constructor:
Lets say there is a situation where we have an existing application
and we need to modify one of its functions to our needs, what can we do?
First option is to override the function by writing another one with the same name, the last
function counts. The problem is there are some cases where this workaround will not do.
Another option is actually manipulating the function code. How can we achieve that?
Before we will answer that question lets take a look at the following example:

alert(Foo);


The result of the above code is a popup window and the string representation of 'Foo' function is being displayed within.
I like this :) it means that we can pass a function as an argument extract its
content and even manipulate it. First lets take a look at the following example:

function foo1(x) {
    this.x = x;
}
function foo2(func) {
    this.x = 6;
    var x1 = new func(x);
    alert(x1.x);
}
foo2(foo1);


In the above example we can see some of JS power.
Now, lets get back to the former example and by using JS Function (with a capital 'F')
Lets say you need to create a simple function which popups an alert
using 'Function', we can do the following:

var foo = new Function("value", "alert(value)");
foo('s');


You can see that the first argument "value" is the function's parameter, the next argument
is the function's body. 'Foo' is now an anonymous function.
Now, lets get back to our previous example ('Foo' function) and add to its result a divide member, as followed:

 function Foo(x, y) {
    this.x = x;
    this.y = y

    this.calc = function() {
        return { sum:(this.x + this.y),
             mult:(this.x * this.y),
             sub:(this.x - this.y) }
    }
}

function manipulator(func, from, to) {
    var prepare = func.toString();
    var prepare = prepare.replace(from, to);
    try {               
        var prepareArgs = prepare.substring(0, prepare.indexOf("{")+1);
        prepareArgs = prepareArgs.substring(prepareArgs.indexOf("(")+1, prepareArgs.indexOf(")"));
        prepareArgs = prepareArgs.split(",");
        prepare = prepare.substring(prepare.indexOf("{")+1, prepare.lastIndexOf("}"));
       
        return new Function(prepareArgs, prepare);
    } catch (e) {
        alert("Name: " + e.name + "\nDescription: " + e.description);
    }
}

var Foo = manipulator(Foo, "sub:(this.x - this.y)", "sub:(this.x - this.y), divide:(this.x / this.y)");
var foo = new Foo(5, 5);
alert(foo.calc().divide);



Namespaces & Closure:
When I see the common use of JS I can see bunch of global functions mixed with global variables.
In the good scenario we can find this whole bunch included in a resource file common.js or main.js.
A better way is putting your code in a sub global areas by using Namespaces.

var tikal = {};
tikal.foo = function(){};


Lets aim a little higher, In the next example we can see how we can use closures to create a private
namespace and expose its public methods to the public namespace. If you'll run the next example,
you'll see that foo will be set to value 666.

var com = {tikal:{}};

(function() {
    var foo = 1;
    function getFoo(){return foo};
    function setFoo(pFoo){foo = pFoo};

    var ns = com.tikal;
    ns.getFoo = getFoo;
    ns.setFoo = setFoo;

})(); // end annonymous function definition and invoke it.

com.tikal.setFoo(666);
alert(com.tikal.getFoo());


The same code can be written as follow:

var com = {tikal:{}};
com.tikal = function() {
    var _foo = 1;

    return {
        getFoo: function() {
            return foo;
        },
        setFoo: function(pFoo) {
            foo = pFoo;
        }
    }
}();

com.tikal.setFoo(666);
alert(com.tikal.getFoo());


As you can see no instance should be created the public functions are staticly being called
and the private variables maintain their state. But what if we need to instantiate a Class and call
repeatedly its methods, we can then do the follow:

var animals = (function() {
    // private area
    function Dog(name) {
        this.name = name;
    }
    Dog.prototype.bark = function() { return "Woof! " + this.name };

    // public area
    return {
        Dog: Dog
    }
})();


// We can also use prototype in here: animals.Dog.prototype.bark = function() { document.write("Woof! " + this.name) };
var fido = new animals1.Dog("fido");
fido.bark()

var rover = new animals1.Dog("rover");
rover.bark();



To be continued...

  •   Prototype

  •   Custom Event

  •   AOP

  •   Listener override

  •   CSS

  •   Native AJAX

  •   Canvas

  •   Misc

 

 

Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com