5 Minute JavaScript #7 Closures

In the previous blogpost we discussed a way to reduce the amount of global variables by using namespaces. Today, we will be looking into a different way to hide functions and variables.

If you write JavaScript code on a regular basis (without being an expert) you might have heard about ‘closures’. While closures are becoming increasingly popular in other programming languages as well, JavaScript allows you to take them one step further.

Sometimes you want to run a block of code, define properties, etc without having to worry about the global object (5 MIN JS #4). If this is the case you could use a closure function to which you can bind your variables.

<script>
    var free = 'We want this variable to be global';
    var bound = 'We want to make this variable non-global';
</script>

Replaced this by:

<script>
var free = 'A free variable';
(function(){
    var bound = 'A bound variable to an anonymous function';
    function boundFunction () { /* cannot be called outside the closure */ }
}());
</script>

This is a function that is executed immediately. This means that the code result might be the same, but in the second example the ‘bound’ variable isn’t added to the global object. The difference between the ‘free’ and ‘bound’ variable is that the ‘bound’ variable is cleaned up after the function execution ends. This happens because its context is finished executing and it isn’t bound to a higher scope (such as the global object).

Some frameworks help you in writing better code without you knowing it. For example in jQuery, you are advised to use the $(document).ready(function() { }); function. Thanks to jQuery the programmer is actually using a closure, he’s defining a function that is passed along as parameter to the ready function. But this also means that all the variables defined while initializing are also set to ‘non-global’.

5 Minute JavaScript #6 Namespaces

Last post we noticed that variables can easily be attached to the global scope. This isn’t a good thing. The more variables are linked to the global scope the more chance you have creating conflicts.

A great way to reduce the impact of your code on the global object is to define namespaces. We do this by creating one global object that we extend with extra modules which on their turn can be extended with new functionality and properties.

// Initialize this first before any other code
var Application = {};

// might be in another file for example module1.js
Application.module1 = {
	calculate: function () {},
	redirectTo: function () {}
};

// might be in another file for example module2.js
Application.module2 = {
	calculate: function () {},
	doSomething: function () {}
};

// In application
Application.module1.calculate();
Application.module2.calculate();

By defining the Application namespace (and the two module ‘packages’) we have no conflict between the two difference calculate functions. We also know at all times what function we are calling from which subproject or module.

This is a first step into creating frameworks, but it’s not the best solution. Most daily JavaScript users know this pattern and are using it to reduce conflicts. However, we know that in JavaScript functions are very important, so maybe we are able to improve this solution by throwing in some functions?

5 Minute JavaScript #5 Globally Implied

JavaScript uses the var-statement to declare variables and bind them to a scope. But this statement isn’t mandatory. In JavaScript you are allowed to define a value without this statement. When you do not use the var-statement, the variable will be added to the Global Object (see previous post).

function f () {
	x = 1;
}

Whenever we execute f we won’t bind the x variable to f, instead we will define a new property named x on the global object. So, it definitely seems like a good plan to always use the var statement! But sometimes you can just forget to define the value before using it…

function f () {
    var x;  // (= undefined)
    /* some code */
    if (/* something is true */) {
	  x = 'something';
    } else {
	  x = 'something else';
    }	

    return x;
}

If in this example you had forgotten to declare x before using it (in the if-statement), you would have declared x globally. Since these kinds of issues are hard to detect, you will need to be disciplined in your variable declaration because JavaScript won’t force you to do it.

When you define x without any value, you are actually saying “in this scope there is a variable with name x, but its value is undefined”. The next time you will attach a value to the variable you won’t need to use the var-statement.

5 Minute JavaScript #4 Global Object

Now that we know how to create scopes and how to bind variables to them, we should also be aware of JavaScript’s global object. Whenever we declare a variable with the var-statement, the variable will be bound to the nearest scope. But what happens when there is no scope? It needs to be attached to something, right?

<code>
	var x = 1;
<code>

In this example, there is no function to which x can be bound. Therefore x gets added to the global object. Being part of the global object means that the value is accessible from everywhere. This might sound exciting, but you have to know that this can cause a lot of problems. A filthy global object is a ticking time bomb, waiting to explode and become conflict issues.

Some JavaScript create multiple script files containing functions and include them in their HTML-page based on some back-end logic.

script-module1.js

function calculate(){}
function redirectTo(){}

script-module2.js

function calculate(){}
function doSomething(){}

Imagine these files to be part of two different modules, designed by two different teams and combined into one application. If these two files get included into one HTML-file, a conflict rises for the calculate function and unexpected behaviour is possible. This is because functions are also values and we know that values that aren’t bound to a scope are part of the global object.

So although these functions are in different files, they can be combined into one HTML-page and that’s when conflict issues tend to rise. These conflicts are sometimes very hard to find (especially in large code bases).

If you want to know what’s defined in the global object, you can always check the window object (only in browsers, NodeJS works differently). This object contains all native JavaScript functions and all the functions/variables you have defined globally.

5 Minute JavaScript #3 var-statement

In our previous post we discussed the importance of functions and scopes. The var-statement is narrowly linked to these concepts. Most Object-Oriented languages are statically typed. This means that you will need to declare the type of the variable you want to define before compiling. JavaScript however is dynamically typed and every value is defined with a var-statement.

var number = 1;
number = "Now it’s a string";

If the type of a variable can change, it gets tricky. You should never do that, but JavaScript allows it.

Back to the var statement. Using this statement is just like saying “name this value and bind it to the nearest scope”. An example:

function f () {
    var variable = "value";
}

The var-statement will make the “value” with the name ‘variable’ accessible in the context (scope) of the function f (because this is the first scope it encounters).

It’s important to know that only functions can create scopes. So, visibility of a variable will only be bound to a function. This means that functions become increasingly more important in JavaScript. Check out our previous blog post if you want to know a little more about functions and scopes.

Triggering Dynamic actions from javascript code in APEX

Since APEX 4.0, dynamic actions have made our lives easier. But sometimes they feel a little restrictive in what you can do with them. Executing them upon the successful completion of another dynamic action, for example, or forcing a dynamic action to fire, triggered by something that happened in your javascript code.

APEX 4.2

Since APEX 4.2, there is a way to do this easily.

We start by creating the application process that needs to be triggered. It is important that you choose the event type “Custom”, and give it a name.

da1

To keep the example simple, I made a true action executing some javascript and printing it to a region on the page.


$('#dynamicactionresult > .uRegionContent').html('Dynamic action triggered successfully');

The hardest part is over now. All that’s left to do, is trigger the dynamic action from javascript. This can be done with the following piece of code:


$.event.trigger('TriggerMe');

Where TriggerMe references the name of your “custom event”.

Older versions of APEX 4.x

The above only works from APEX 4.2. However, for the older versions of APEX 4 there is a workaround!

First, we make a hidden page item, allow it to be accessed by javascript and set protected to “No”.

da2

Next, we create a dynamic action that triggers on change of this item, executing some javascript code as mentioned before.

da3

Finally, we trigger this application process by forcing a change-event on the page item. This can be done with the following piece of code.

apex.event.trigger($("#P1_DYNAMIC_ACTION_TRIGGER"),"change","");

5 Minute JavaScript #2 Scopes

In our last blog post we showed that JavaScript is different from Java when talking about functions. Another difference with regard to these object-oriented language lies in the code scope. Scopes are blocks of code in which a variable is known. It’s a context in which some variables are accessible, others are hidden, destroyed, etc.

In Object-Oriented languages such as Java, everything inside a  { } – pair is confined into a scope. For example:

if (true) { String s = "Scoped"; }

System.out.println(s); // s does not exist

In JavaScript however, only variables declared inside a function are scoped. This is a very important difference. When working with if-statements or for-loops, the variables you define there aren’t scoped to the code block, but to the parent function.

function f () { var x = "not accessible outside function f"; }

if (true) { var x = "also available outside the if-statement"; }

for (var i = 0; i < length; i++) { /* code */ }
console.log('i is known outside the for', i);
    

You might think that this is a shortcoming in JavaScript, but it’s not. This way of scoping is used in many functional languages, it’s just another way of thinking.

So when you are thinking about encapsulating properties and variables, remember that you will have to use functions.