Jump to content
Larry Ullman's Book Forums
Sign in to follow this  
HartleySan

Deciding On The Scope For A Variable

Recommended Posts

This debate may be so trivial and pedantic that it doesn't warrant a discussion at all, but all the same, I have been wondering about something in particular recently.

 

Recently, I've been thinking about the best scope to set for certain variables. For example, if I was using a variable i as the control variable for all my for loops in functions, I'm wondering whether it makes sense to declare one global i variable for all the for loops, or to locally declare an i variable for each for loop. As an example:

 

Global i

 

(function () {

 

'use strict';

 

var i;

 

function f1() {

 

for (i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

function f2() {

 

for (i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

function f3() {

 

for (i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

}());

 

In the above case, since everything is wrapped in a self-invoking function, I wouldn't have to worry about polluting the global namespace with i. Also, I only have to declare i once, and then I can freely use it in functions f1, f2 and f3.

 

While I'm not exactly sure how declaring variables in JS works internally, I feel like declaring the variable i once is more efficient (CPU-wise) then redeclaring it every time f1, f2 or f3 is invoked. Of course, there's the downside of i sitting in memory until the page is closed.

 

Then there's the alternative, which is to declare i locally in each function. For example:

 

Local i

 

(function () {

 

'use strict';

 

function f1() {

 

for (var i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

function f2() {

 

for (var i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

function f3() {

 

for (var i = 0; i < 10; i += 1) {

 

// Code here

 

}

 

}

 

}());

 

This obviously has the advantage of i only being in memory when it's needed, but somehow, constantly redeclaring it seems like a waste.

 

Perhaps ultimately, it's a call between assessing how often the functions f1, f2 and f3 are called above, and based on that, making a best guess as to whether a global i or a local i would be better. In other words, if f1, f2 and f3 are rarely called, then maybe local i's would make more sense, but if the functions are called often, then maybe a global i would be better.

 

Again, I know this is a fine point of the language that's perhaps not even worth worrying about, but all the same, if anyone has any opinions, please share them.

 

Thank you.

 

P.S. I apologize for the cruddy formatting, but I have to use IE6 at work.

Share this post


Link to post
Share on other sites

I would always declare variables as locally as possible. Only use a broader scope if necessary. I have never seen anyone, in any language, using a global (or less-local) variable as a loop counter. Whatever the overhead required to create and delete it, it can't be much. And even if you use a self-invoked function, you're still making the loop variable larger in scope than need be (i.e., you're polluting the outer function scope). Plus you may end up having created a variable that never gets used. And the variable can't be deleted at any point in time. I just can't imagine it makes sense to do that, but it is an interesting question to consider.

Share this post


Link to post
Share on other sites

All right. Thanks for your input. When it comes to the inner workings of JS (or any language for that matter), I wasn't sure how "inefficient" it was to continually be allocating memory for virtually the same variable versus allocating the memory once and keeping the variable around.

 

The main thing that spawned this question was the fact that I have been reading recently about Java's garbage collector, and a big reason many Java applications get laggy is because of how the internal engine handles garbage collection. To that end, I was just wondering if minimizing the amount of garbage collections (at the sake of using more memory) would be advisable or not.

 

Anyway, thanks for your quick response.

Share this post


Link to post
Share on other sites

Variable instantiation and object creations are pretty cheap. It's loop iterations you want to think about reducing. (If it's possible to remove an inner loop, do it)

 

I don't know how JS garbade collection works, but Java removes any unused references and values. The reason this sometimes fails in Java is because you still have references to unused objects someplace you would not think about removing them. It's more of programming errors than about the garbage collector itself. I've never had any such troubles in the time I've developed java.

Share this post


Link to post
Share on other sites

Antonio, thanks for your input. That's good to know.

I must admit that I'm still rather green when it comes to certain aspects of programming.

 

Nowadays, I quite often find myself declaring "global" variables within a giant self-invoking function that wraps my entire code.

However, from now on, I think I will start moving all variable declarations into function definitions, even if it means declaring variables more often, etc.

Share this post


Link to post
Share on other sites

Move towards objects. That's really the way to go. If you think you have to many variables, you are probably right. The problem though is NOT speed or memory, because that's cheap with variables. It's that your code gets hard to maintain and understand. You should know that an object is really not taking up more memory than your common string or integer. Objects are not these huge, heavy things. It's the algorithms for sorting, filtering and validation (of array structures) you'd want to be critical about.

 

As I mentioned to someone else. I created 300 000 Card objects (yellow cards in football) which itself holds a Player and a DateTime object. How much time did that take? 0.3 seconds for the instantiation. How long did this take to print (echo) to screen? About 1.8 seconds, (which is to long) but who would need to create 900 000 objects (1 card, 1 player, 1 datetime) in one PHP-script? The reason why I tell you this is to understand that objects are cheap too. Learn object-oritented design, and your code will get a lot better FAST.

 

I would really recommend this book: http://www.amazon.com/PHP-Object-Oriented-Solutions-David-Powers/dp/1430210117

  • Upvote 1

Share this post


Link to post
Share on other sites

Antonio, thanks for the realistic example. And yeah, I know what you mean. I do generally deal with objects, but I was just trying to think of what's the most efficient way to deal with variables.

Share this post


Link to post
Share on other sites

Move towards objects. That's really the way to go. If you think you have to many variables, you are probably right. The problem though is NOT speed or memory, because that's cheap with variables. It's that your code gets hard to maintain and understand. You should know that an object is really not taking up more memory than your common string or integer. Objects are not these huge, heavy things. It's the algorithms for sorting, filtering and validation (of array structures) you'd want to be critical about.

 

As I mentioned to someone else. I created 300 000 Card objects (yellow cards in football) which itself holds a Player and a DateTime object. How much time did that take? 0.3 seconds for the instantiation. How long did this take to print (echo) to screen? About 1.8 seconds, (which is to long) but who would need to create 900 000 objects (1 card, 1 player, 1 datetime) in one PHP-script? The reason why I tell you this is to understand that objects are cheap too. Learn object-oritented design, and your code will get a lot better FAST.

 

I would really recommend this book: http://www.amazon.co...s/dp/1430210117

 

It is a good book! :D

Share this post


Link to post
Share on other sites

Okay, I got to thinking about this variable scope business again (however dangerous that may prove to be).

Basically, I was messing with a JS script that handles all the functionality for my site, and I started changing all the variables to local variables. However, doing so created all sorts of headaches in terms of passing various variables to functions. In particular, for event handlers, instead of being able to do something like the following:

 

for (var i = 0, aLinksLen = aLinks.length; i < aLinksLen; i += 1) {

 aLinks[i].onclick = someFunction;

}

 

I get stuck with the following:

 

 

for (var i = 0, aLinksLen = aLinks.length; i < aLinksLen; i += 1) {

 aLinks[i].onclick = function () {

 someFunction(var1, var2, var3, var4);

 };

}

 

The variables being passed to someFunction in the second example are all DOM references/arrays, which, as far as I can tell, are definitely inefficient to calculate multiple times. At the same time though, having all those anonymous function definitions stack up in memory seems like a total waste as well.

 

So now, I'm starting to come to the conclusion that sometimes, "global" variables (i.e., variables declared with a self-invoking function, but not within any inner-functions) are not such a bad thing in some cases. For example, arrays of DOM element references that I will use many times, etc. make more sense to be "globally" available, do they not?

 

As such, I'm thinking about declaring a "global" settings object to handle all the stuff that's used many times and is inefficient to calculate many times. I have seen many JS modules do this, and it doesn't seem bad.

 

Anyone, please share your thoughts. Thank you.

Share this post


Link to post
Share on other sites

It looks like you can create objects and properties in JS. (I don't know JS)

 

Instead of creating global values, declare var1 to var4 as object members, and build an array with these values. When the loop is done, return the array. I will try to illustrate this in PHP.

 

The class that does calculations:

 

class someFunction {

private $var1, $var2, $var3, $var4;
private $calc = array();

public function __construct( $var1, $var2, $var3, $var4 ) {
	$this->var1 = $var1;
	// Same of 2, 3, 4
}

public function calculate( $iterations ) {
	for ( $i = 0; $i < $iterations; $i++)
	{
		// Some calculation here
		$this->var1 += 0.5;
		$this->var4 *= 72;

		// Add calculation to array
		$this->calc[] = array( $this->var1, $this->var2, $this->var3, $this->var3);
	}
	// Return array when done calculating
	return $this->calc;
}

   public function getValues (
    return $this->calc;
   }

}

 

Use your new class:

 

// Assign som values to variable
$var1 = 12;
#var4 = 2;
.....

// Create calculation object
$calc = new someFunction($var1, $var2, $var3, $var3);

// Save calculations to Array
$aLinks = $calc->calculate( 100 );

// Then you need these calculations someplace else....
$aLinks = $calc->getValues( );

(other code)

// And some other place....
$newLinks= $calc->getValues( );

 

The object will hold this information for you instead of global variables. If you do not need an array, simply remove the array and return the single members by functions like getVar1(), getVar2. This way, calculations are done once and then saved inside the object instead of saved globally. It just makes more sense to me. If you need these values in other code, you pass along the object or the values.

 

I don't know if you can do something like this in JS, but that would be the best way. Global variables are no good coding style in most cases, but your case MIGHT be legit. Remember that I don't know JS, but I speak from a general programming perspective. The most important thing is that the code WORKS. When it works, improve it. :)

Share this post


Link to post
Share on other sites

What happened with the under scores for your private or protected properties, if you are recommeding David Powers. He likes to follow the Zend way of writing his code. Yes and in oop coding you would defeat the whole purpose of encapsulation if you were using global variables, Old David says if you don't know what scope to declare a property use protected.

Share this post


Link to post
Share on other sites

Antonio, thanks for the advice.

When I said "global" in my post, the quotes were intentional to imply pseudo-global variables, not actual global variables.

 

There's no real PHP parallel to be made (well, maybe classes with protected/private variables), but in JS, you can create what's called a self-invoking function, wrap all your code in that, and essentially, you have no variables in the global namespace. That's not the issue at hand here, though. It's not so much a matter of occupying the global namespace as it's a matter of the most CPU- and memory-efficient way to declare and handle variables.

 

Anyway, it's hard to explain if you're not familiar with JS. Sorry.

Share this post


Link to post
Share on other sites
What happened with the under scores for your private or protected properties, if you are recommeding David Powers.

 

I recommend his book, but I have my own coding style.

 

Yes and in oop coding you would defeat the whole purpose of encapsulation if you were using global variables, Old David says if you don't know what scope to declare a property use protected.

 

That's right. I like this explanation. "You don't know how a toaster works. It turns your bread into toast, but you don't care how."

 

For the second part, I would say that really depends, but if you read on, he'll elaborate on when to do what later on.

 

Jon: Yeah, as said I don't know JS. If you think that's a good way, I take your word for it. I trust your skills.

Share this post


Link to post
Share on other sites

Well, I'm trying to find the best way, which is why I'm asking.

Larry warned against even pseudo-global variables within a self-invoking function, but I'm starting to think that sometimes they're necessary in order to keep things as efficient as possible.

Anyway, kinda hoping Larry will chime in eventually.

Share this post


Link to post
Share on other sites

 

 

I recommend his book, but I have my own coding style.

 

 

 

That's right. I like this explanation. "You don't know how a toaster works. It turns your bread into toast, but you don't care how."

 

For the second part, I would say that really depends, but if you read on, he'll elaborate on when to do what later on.

 

Jon: Yeah, as said I don't know JS. If you think that's a good way, I take your word for it. I trust your skills.

 

In most of the examples Ive worked through we never used public properties it was either private or protected. The David powers is okay but I do like Matt Zandstra as well. Matt may use every word in the English dictionary and make the stuff harder to understand than David but what I like with Matt is he shows you what happens when you don't use oop against actually using it. I am reading both books along side each other at present.

  • Upvote 1

Share this post


Link to post
Share on other sites

A few thoughts...

 

Antonio, I would distinguish between objects in general, objects in PHP, and objects in JavaScript when saying whether or not objects take up a lot of memory and are "heavy". There are big differences between how each language handles objects. And the size requirements and performance of objects will depend upon not just the data they store, but also the methods they define, whether they inherit from other objects, etc. A generic object in JavaScript is a pretty efficient beast, because it's JavaScript's native data type. Also, Antonio, let me know if you'd like a copy of the JavaScript book (as thanks for all the help you've provided here over the years).

 

Hartley, I definitely don't think global variables are always a bad thing. Some times they're a better solution than others, as you're thinking. The only truly bad thing, in my opinion, is to accidentally create/use global variables or, to a lessor extent, use globals unnecessarily. Later in the book I have some examples of using non-local scope variables to represent DOM elements. I would also recommend, when going the global route, creating only a single global object.

 

Thanks for this thread! It's a good one.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...