Inside Microsoft Web Bulder

August 1999

Variable Scope and Parameter Passing

Regardless of the language or the development environment, an understanding of how values are stored and shared in a programming application is fundamental to the art of programming. In this article, we'll look at some of these fundamental concepts, and illustrate them with a practical application. The application that we'll use is shown in Figure A.

Figure A: We've created a pop machine simulation to illustrate the concepts

[ Figure A ]

The HTML code that created the page is shown in Listing A. You can see from the figure that we're simulating a vending machine that dispenses carbonated beverages (a pop machine or a soda machine, depending on your locale).

Listing A: HTML code to create our vending machine Web page

<HTML>
<HEAD>
<TITLE> Variable scope and parameter passing </TITLE>
<STYLE>
LABEL {font-size:14}
.invent {position:absolute;left:100;width:50}
</STYLE>

<!Script goes here

</HEAD>
<BODY onload = init()>
<INPUT TYPE = "button" style = "width:50" Value = "5c" 
	onclick = addsum(5)> 
<INPUT TYPE = "button" style = "width:50" Value = "10c" 
	onclick = addsum(10)> 
<INPUT TYPE = "button" style = "width:50" Value = "25c" 
	onclick = addsum(25)><BR><BR>
<INPUT TYPE = "text" style = "width:125" id = amount><BR>
<INPUT TYPE = "button" ID = cola style = "width:150" 
	Value = "Cola 75c" 
	onclick = "buypop(pop0,'Coca Cola',75)"> 
<INPUT TYPE = "button" ID = rootbeer style = "width:150" 
	Value = "Root Beer 75c" 
	onclick = "buypop(pop1,'Root Beer',75)"> 
<INPUT TYPE = "button" ID = lemon style = "width:150" 
	Value = "Lemon Lime 75c" 
	onclick = "buypop(pop2,'Lemon Lime',75)"> <BR>
<INPUT TYPE = "button" ID = icet style = "width:150" 
Value = "Iced Tea 80c" 
onclick =  "buypop(pop3,'Iced Tea',75)">
<INPUT TYPE = "button" ID = oj style = "width:150" 
	Value = "Orange Juice 85c" 
	onclick =  "buypop(pop4,'Orange Juice',85)" >
<INPUT TYPE = "button" ID = berry style = "width:150"
	Value = "Very Berry 85c" 
	onclick = "buypop(pop5,'Very Berry',85)"><BR>

<INPUT TYPE = "text" style = "width:200" id = dispense>
<BR>
<b> Inventory
<BR>
<LABEL> Coca Cola
<INPUT TYPE = "text" class = invent id = pop0><BR>
<LABEL> Root Beer 
<INPUT TYPE = "text" class = invent id = pop1><BR>
<LABEL> Lemon Lime
<INPUT TYPE = "text" class = invent id = pop2><BR>
<LABEL> Iced Tea 
<INPUT TYPE = "text" class = invent id = pop3><BR>
<LABEL> Orange Juice
<INPUT TYPE = "text" class = invent id = pop4><BR>
<LABEL> Very Berry
<INPUT TYPE = "text" class = invent id = pop5>
</BODY>
</HTML>
To purchase a beverage, the user first enters some amount of money by clicking on any combination of the coin buttons (5c, 10c, or 25c). The amount entered appears in a text box below the buttons.

After the user is satisfied that he's deposited the correct amount of money, he chooses a beverage by clicking on one of the beverage buttons. If the correct amount of money has been deposited, the user receives a message thanking him for his order, and indicates the type of beverage he'll receive. Figure B illustrates the page after a transaction has taken place.

Figure B: If the correct amount has been deposited, the user is told that his beverage is being dispensed.

[ Figure B ]

We'll look at the script that makes it all happen in just a minute. For now, let's take a look at the concepts that allowed us to create this application.

Variable scope

Variables are used to hold the data that your program needs to perform its task. You can picture variables as a series of pigeonholes in an old-fashioned desk, or, for a more contemporary image, the mail slots in a company mail room. Each variable holds some piece of information (a string, a number, or an entire object). The piece of information is called the variable's value. A variable's scope is the extent to which the variable is recognized within a document. A variable with global scope (that is, a global variable) is recognized by all parts of a Web page document for as long as it's loaded in a browser window or frame. That means that all statements in a script, both inside and outside of functions, can have direct access to a global variable's value. Direct access implies that statements can retrieve the values of a global variable, or modify its contents. The values of global variables persist for as long as the page is loaded.

A local variable is defined within a function, and can be accessed only within that function. Any values given to a local variable only persist as long as the function is currently processing, and any statements outside of the function can't recognize these variables. Listing B contains the script for our vending machine application, and illustrates the use of both global and local variables.

Listing B: Illustrating variable scope and parameter passing

<SCRIPT language = "JavaScript">

var sum = 0
var drinks = 6

function init() {
	document.all.amount.value = "
	var i
	for (i = 0; i < drinks; i++) {
		obj = eval("pop" + i)
		obj.value = 100
	}
}
		
function addsum(amt) {
	sum = sum + amt
	document.all.amount.value = sum 
}

function buypop(invnum,drink,price) {
	var amt
	amt = sum - price
	document.all.amount.value = amt
	sum = amt
	if (amt < 0) {
	document.all.change.value = "Put in more money"
		document.all.dispense.value = "
	} else if (amt> 0) {
	document.all.change.value = "You get " + sum + 
			" cents change"
	} else {
		document.all.change.value = 
			"Thank you for your order"
	}
	if ((amt > 0) || (amt == 0)) {
	document.all.dispense.value = "One " + drink + 
			" coming up"
		inventory(invnum)
	}
}

function inventory(num) {
	if (num.value == 0)
		alert("Inventory depleted")
	else
		num.value--
}
</SCRIPT>

Going global

The variables sum and drinks are both global, since they're declared outside of any function. To make your scripts more readable, it helps to put all global variables at the very beginning of your scripts.

The variable sum needs to be global because it needs to persist as long as the page is loaded. Initially, it's set to 0 when it's declared. It's then accessed by two different functions. The addsum function keeps a running total of the money deposited with the statements

	sum = sum + amt
	document.all.amount.value = sum 
The function bypopalso uses sum to calculate the amount of money remaining after a user has purchased a soda, and to store the new amount. This is accomplished in the statements:
amt = sum - price
...
sum = amt
We've also defined drinks as a global variable. drinks holds the number of different sodas offered, for use in our for loop:
	for (i = 0; i < drinks; i++) {
		obj = eval("pop" + i)
		obj.value = 100
	}
Although we could have used a literal value here (the number 6, for example), declaring drinks as a global variable makes it easier to change the value in case we decide to offer additional beverage choices at a later date. This would have been particularly helpful if we'd needed this value in more than one place in our script. In that case, if we'd used a literal, we would have had to change the value everywhere it was used; using one global value allows us to make the change much more easily.

Keeping it local

The buysoda function declares two local variables, i and amt. The variable i is clearly local. It performs a task only within that function, and is only required for as long as the loop within the function is running. The variable amt is also only used locally to temporarily store the current amount deposited, after the user has selected a purchase, as in:

	var amt
	amt = sum - price
Note that since the variable amt in addsum is only known locally to that function, it's a completely different amt than the one that's used in buypop.

A good programming rule of thumb is to declare as few global variables as possible, and to keep your variables local. This improves the readability of your code, and limits your ability to accidentally change a value somewhere that you didn't intend.

Function parameters

In order to work together, functions must share data. To pass data to a function, the calling statement places values within parentheses after the function name, as in:

onclick =  "buypop(pop4,'Orange 
	Juice',85)"
The called function receives these values in variables that are also placed inside parentheses after the function's name:
function buypop(invnum,drink,price)

Matching parameters

There are a few things to point out here. Notice, first of all, that parameters are matched in the order they appear in parentheses. In our example, the object pop4 will be passed into the variable invnum, the string Orange Juice will be passed into drink, and the number 85 will be passed into the variable price.

JavaScript is forgiving if the number of parameters passed doesn't match the number of parameters in the function definition. If a function is defined with three parameters, and only two are passed in the call, the third parameter is assigned a null value. If the calling program were to contain three, and the function only two, the third one is just ignored.

Using parameters

Take a look at buypop to see how the parameters that have been passed can be used. The value 85 that was passed to price is subtracted from sum, and the string Orange Juice is included in the text box message with the statement:

document.all.dispense.value = "One " + 
	drink + " coming up"
Although buypop also receives invnum as a parameter, it doesn't use that value itself. Instead, it passes invnum to the inventory function, with that statement:

inventory(invnum)

The inventory function then uses invnum to decrement the inventory for a particular brand of beverage each time one is purchased.

Passing objects

Our vending machine application also illustrates another important concept: how functions can access elements on a Web page. Let's look at two different examples.

Referring to objects by ID

When we call buypop, as in:

onclick =  "buypop(pop4,'Orange 
	Juice',85)"
the first parameter is the actual object that has been assigned that ID. This means that in the function itself, we can treat the object directly, so that when we pass it on to inventory in the statement

inventory(invnum)
the inventory function can access the object simply by name:
function inventory(num) {
	if (num.value == 0)
		alert("Inventory depleted")
	else
		num.value--

Creating objects from strings

Now take a look at the init function, the for loop in particular. We want to access all of the text boxes that are named pop0, pop1, etc. To actually access the objects, we can create a string for each one using the for loop. We then use the eval method, which can convert a string to an executable JavaScript statement or expression. The eval method converts the strings pop1, pop2, etc. to their equivalent object references:

	for (i = 0; i < drinks; i++) {
		obj = eval("pop" + i)
		obj.value = 100
	}
}

The this keyword

One other way to pass objects is by using the JavaScript keyword this, which refers to the object making the function call. By passing this up to a function, we can refer to the object itself, or, by passing this.form, we can refer to any other object on the current form. We provided an in-depth discussion of the this keyword in "Just what is this?" last month.

Conclusion

Good programming practice recommends that you keep your global variables to a minimum. Instead, use local variables wherever you can, and try to pass in any data that your functions need. This makes your scripts more readable, and also cuts down on debugging. On the other hand, if you have a value (like drinks) that will stay constant through the life of the application, but may change at a later time, avoid using literal values, and replace them with global ones.

Copyright © 1999, ZD Inc. All rights reserved. ZD Journals and the ZD Journals logo are trademarks of ZD Inc. Reproduction in whole or in part in any form or medium without express written permission of ZD Inc. is prohibited. All other product names and logos are trademarks or registered trademarks of their respective owners.