In: Categories » » AJAX » Using Functions to Initialize and Make Decisions JavaScript
Using Functions to Initialize and Make Decisions Problem You want to use functions to initialize and make decisions. Theory Usually when you write a piece of code where a change of logic needs to take place based on a context, you use a decision structure. For example, say you are implementing a light switch using a program. You turn on the light if the light is off, and you turn off the light if the light is on. The behavior of the program is determined by the conditions. One example behavior that deserves a closer look is initialization. Initialization typically should happen only if it hasn’t already. Initialization is important because the initialization logic creates the default framework for your application to properly function. Solution For illustrative purposes, let’s go through an example where a function requires an initialization that is embedded within the function. The logic is to perform an initialization if it has not already occurred. The function that is called is defined as follows, and it embeds a call to the initialization.
Tip You could use this type of code to implement a lazy initialization when writing convention-based code that does not perform an explicit initialization.
Source: /website/ROOT/ajaxrecipes/javascript/makingdecisionsinitialization.html
function ClassicalManipulateObject( obj) {
info( "ClassicalManipulateObject", "Starting");
if( !didInitialize) {
DoInitialization( obj);
}
else {
info( "ClassicalManipulateObject", "no initialization necessary");
}
assertEquals( 3, obj.value);
info( "ClassicalManipulateObject", "Ending");
}
In the example, the bold code relates to the initialization functionality. didInitialize is a flag variable that can be either true or false. If the didInitialize variable is false, then initialization did not take place; if the didInitialize variable is true, then initialization did take place. If initialization did not take place, the DoInitialization function is called. Notice that in the logic is a variable that represents whether initialization has taken place and a function to do initialization. This code is problematic because the variable has to be defined somewhere, and the variable has to be assigned properly somewhere. And somewhere there is a cross-reference between the variable state and the calling of the initialization functionality. One solution is to embed much of the initialization logic in the context of the DoInitialization function. But the fact is that somewhere there is a variable, and somewhere there is an initialization function, and somewhere there is a cross-reference between the variable and initialization function. So where you put the logic is irrelevant in a “big picture” sense.
Another solution is to think of the initialization functionality not as a decision, but as a state. There is an initial state, which is to perform an initialization, and another state to perform no initialization. In a sense, the didInitialize variable is a representation of the state. Keeping that thought in mind, you know that JavaScript treats its functions as objects. Thus, the didInitialize variable could be a function and not a Boolean variable. Treating the state as a variable that references a function makes it possible to simplify the function that requires an initialization. The implementation of the ClassicalManipulateObject function is changed to ManipulateObject, as illustrated in the following code.
Source: /website/ROOT/ajaxrecipes/javascript/makingdecisionsinitialization.html
function ManipulateObject(obj) {
info( "ManipulateObject", "Starting");
InitializeObject( obj);
assertEquals( 3, obj.value);
info( "ManipulateObject", "Ending");
}
In the modified implementation, the bold code again represents the initialization functionality. Here there is no decision just a function call to InitializeObject. You might be thinking, “I could have done the same thing with the decision-based initialization, in that the decision is implemented in InitializeObject.” But this is incorrect, because in the implementation of InitializeObject, there is no decision. The implementation of InitializeObject initializes the variable and then allows the processing to continue. If there is no decision on whether the initialization occurred, and InitializeObject represents a function to initialize the state, then for every call the state will be initialized you can’t call this initialization functionality. The magic is in the fact that JavaScript treats functions as objects. The implementation of InitializeObject is as follows:
function InitializeObject( obj) {
obj.value = 3;
info( "InitializeObject", "doing initialization");
InitializeObject = InitializeEmptyObject;
}
In the implementation of InitializeObject, the obj parameter is initialized to a value of 3, and the bold code shows the reassignment of the InitializeObject function. The reassigned InitializeObject references a function without body, which means that the first time InitializeObject is called, the initialization is carried out, but every call thereafter is an empty function call that does nothing.
This is the complete implementation of the initialization functionality without using a single decision or variable. One advantage of this approach is that you don’t need to figure out which variable to cross-reference with the function. The function takes care of itself, and the caller can keep calling InitializeObject, knowing that everything will be taken care of. Another advantage of this approach is that you are creating a state engine where the next state is determined by the execution of the current state. There is no centrally located decision block that determines the overall flow of execution and needs updating every time a new state needs to be integrated. Normally when writing code in a language such as Java, C#, or C++, you don’t go around reassigning the implementation of defined function. And because this behavior is engrained in the developers’ minds, they don’t even consider doing that. Yet there is absolutely no problem reassigning functions in JavaScript, because functions are objects. Functions are not unique identifiers with unique functionality, as you think of them when working with them in other languages.
The implementation of InitializeObject works and is a complete solution. But there is a little inconvenience in that once InitializeObject has been assigned to an empty function, the initialization functionality is lost until the HTML page is refreshed. For some problems, that is an acceptable solution. For example, you wrap XMLHttpRequest only once because you can instantiate XMLHttpRequest in only a certain browser-specific way. There are some instances, however, when you might want to reset and initialize again, and to be able to do that, you need to wrap InitializeObject into a function within a function, as demonstrated in the following example.
Source: /website/ROOT/ajaxrecipes/javascript/makingdecisionsinitialization.html
function ResetInitializeObject() {
InitializeObject = function( obj) {
obj.value = 3;
info( "InitializeObject", "doing initialization");
InitializeObject = InitializeEmptyObject;
}
}
ResetInitializeObject();
The InitializeObject function is a variable that is assigned a function implementation in the ResetInitializeObject context. Recipe 2-4 shows that there is no difference in how a function is declared, even if it seems odd or out of place. To initialize InitializeObject, the ResetInitializeObject function is called, thus creating the InitializeObject function. And InitializeObject when called will reassign itself to an empty function.
Calling ResetInitializeObject again resets the initialization, allowing InitializeObject to initialize the state and reset itself again. From this example, you can see that a decision does not need to be implemented using an if statement. Another example that illustrates how a state engine could be implemented follows. The example implements a light switch, where if the light is on, it is turned off, and vice versa. Note that not a single if statement is used in this example.
Source: /website/ROOT/ajaxrecipes/javascript/makingdecisionsinitialization.html
function ToggleLight() {
ToggleLight.on = function() {
ToggleLight.curr = ToggleLight.off;
return "on";
}
ToggleLight.off = function() {
ToggleLight.curr = ToggleLight.on;
return "off";
}
try {
return ToggleLight.curr();
}
catch( e) {
info( "ToggleLight", "initialization...");
return ToggleLight.on();
}
}
The function ToggleLight is called whenever you want to switch the light on or off. There is no parameter to indicate an on or an off; that functionality is embedded within the ToogleLight function. In the ToggleLight implementation there are two properties, on and off, both of which are functions. The on function assigns the curr property to off and returns an "on" buffer. The off function assigns the curr property to off and returns an "off" buffer.
To toggle the state, the curr property that is defined as a function is called. The calling of curr is embedded in an exception block, because curr will not be initialized the first time ToggleLight is called. Thus, an exception is generated, and in the catch part of the exception block, the on property (which is a function) is called. Calling on automatically assigns curr and initializes the state. It is important to remember that using an exception block and calling on is acceptable because it is a way of implementing lazy initialization. When writing decision blocks and functions, think about state and the following aspects of this recipe:
• Your program does not need to include as many decisions, because decisions have been replaced by different states.
• You can reassign functions if you can break down the problem into a state engine problem.
• You can be more flexible with reassigned functions because behavior can be substituted dynamically. For example, if you require a two-stage initialization using a decision, that means additional if statements altered in a central location of source code. Using a reassigned function, you are creating a state engine where the behavior can be altered during runtime at the local level.
• When you read through this recipe’s examples, you may have thought, “Why not use a class and object?” The answer is that a function is an object and the examples are object-oriented programming. The code looks odd because we normally assume a function is a feature used to create a class, and that classes typically are not functions. If the notation bothers you, my advice is to let this feature of JavaScript stew in your mind for a bit. You will surely come to see it is a powerful way of programming.
Note For another example of using recursion instead of using decision blocks.
legal notice
Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.
Useful tools and features
related articles
Coding the Contract Using Test-Driven Development Techniques Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally...
2. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...
3. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...
4. Coding Using Conventions and Not Configurations
Coding Using Conventions and Not Configurations Problem You want to make your JavaScript constructs more efficient by applying the Rails “convention over configuration” principle to them. Theory You may already be familiar with the programming platform Ruby on Rails, which is used to build Web applications. The focus of this recipe is not Ruby on Rails, but one aspect of Ruby on Rails namely, convention over configuration (see http://en.wikipedia.org/wiki/ Ruby_on_Rails for m...
5. Advantage of parameterless functions in JavaScript
Using Parameterless Functions Problem You want to take advantage of parameterless functions in JavaScript. Theory JavaScript functions for the most part have parameters. You may think that the previous sentence states the obvious after all, without parameters, what data could be passed to a function? JavaScript has the ability to declare functions that have no parameters, even though the caller of the function has passed parameters to the function. For example, let’s look at...
6. JavaScripot Functions
Treating Functions Like Objects Problem You want to take advantage of the fact that functions are objects (remember, everything is an object in JavaScript). Theory Many people think that a function is some keyword used in JavaScript. A function is also an object that can be manipulated. Knowing that a function is an object makes it very interesting from the perspective of writing JavaScript code, because the code can treat the function like another other object. This mean...
7. Implementing an Error and Exception Handling Strategy
Implementing an Error and Exception Handling Strategy Problem You want to implement a clean error and exception handling strategy in your applications, to make them run more smoothly. Theory Of course, you might argue that one error is a dialog box and the other is generated in the JavaScript console. The fact that one browser uses a dialog box to show an error and the other does not is a browser issue, not an error issue. A concise way of classifying the two errors is to ...
8. Understanding the Behavior of Variables When Implementing Recursion
Understanding the Behavior of Variables When Implementing Recursion Problem You want to implement recursion in JavaScript, and you also want to understand how variables will behave under those circumstances. Theory In JavaScript, you do not need to declare the variable type, or even declare the variable. For example, the following code works perfectly: if( counter == 1) { buffer = "counter is 1"; } document.getEle...
