473,395 Members | 1,679 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Having multiple object instances use the same variable without overriding each other.

Atli
5,058 Expert 4TB
Hi everybody.

This is not so much a problem, since I have already managed to find a solution, but my solution requires the use of the eval() function, which I just hate to use.

The problem is this.
I have an object that has a function. This function needs to call itself in a setTimeout call. Using the "this" keyword from within the callback function will obviously not work, seeing as it would reference the new function rather than the object instance.

So, in an attempt to solve that, I create a reference to "this" before I create the callback function and use that inside the callback function, like so:
Expand|Select|Wrap|Line Numbers
  1. // Minimized the code to get to the point
  2. function Updater(pTargetElement, pMaxValue)
  3. {
  4.     this.update = function(pCurrent)
  5.     {
  6.         self = this;
  7.         window.setTimeout(function(){
  8.             self.update(pCurrent);
  9.         }, 50);
  10.     }
  11. }
  12.  
And this works... almost.

The object is meant to manipulate an element, taking an initial value and counting up until the max value is reached, displaying the current value in the given target element.
And this does exactly that... if I have only one instance of the object running at a time.

Once a second instance is in play, the two will be fighting over the "self" variable, which is apparently created in a scope that both instances use.

As a result, if a first instance sets the "self" value to itself and fires of the setTimeout, a second instance may be called before the timeout is reached, altering the "self" variable, which is then reflected in the timeout calls from both objects.

This effectively doubles the effect on the second instance, while the first instance is left unchanged.

And this is my problem. How do I create the "self" variable in a scope that is unique to each object instance? So when the second instance is called, it will not alter the variable created by the first instance.

But, like I said, I managed to find a solution by using the eval() function.

My thinking was that the main problem is the second instance re-using the same variable. So I created a "dynamic" variable by creating a random number and turning that into a variable by running it through the eval function.
Like so:
Expand|Select|Wrap|Line Numbers
  1. function Updater(pTargetElement, pMaxValue)
  2. {
  3.     this.update = function(pCurrent)
  4.     {
  5.         rand = Math.floor(Math.random() * 10000);
  6.         eval("self_" + rand + " = this;\
  7.               window.setTimeout(function(){\
  8.               self_" + rand + ".update(" + pCurrent + ");\
  9.               }, 50);");
  10.     }
  11. }
  12.  
This is obviously flawed. Even tho it is a pretty safe method, there is always a chance that the random numbers collide causing a problem, not to mention that this will create a bunch of random variables that are left lying around.

This can be used, and my use of it will be limited so the potential of problems is minimal, but there just has to be a better way.

This is the full code I am using to test this, just in case:
Expand|Select|Wrap|Line Numbers
  1. function Updater(pTargetElement, pMaxValue){
  2.     this.targetElement = pTargetElement;
  3.     this.maxValue = pMaxValue;
  4.  
  5.     this.update = function(pCurrent){
  6.         if (pCurrent >= this.maxValue) {
  7.             return;
  8.         }
  9.         ++pCurrent;
  10.         this.targetElement.innerHTML = pCurrent.toString();
  11.  
  12.         rand = Math.floor(Math.random() * 10000);
  13.         eval("self_" + rand + " = this;\
  14.               window.setTimeout(function(){\
  15.               self_" + rand + ".update(" + pCurrent + ");\
  16.               }, 50);");
  17.     }
  18. }
  19.  
  20. function bodyOnLoad(){
  21.     for (i = 1; i <= 3; i++) {
  22.         eval("window.setTimeout(function(){\
  23.               updater = new Updater(document.getElementById(\"Counter" + i.toString() + "\"), 50);\
  24.               updater.update(0);\
  25.               }, (250 * " + i.toString() + "));");
  26.     }
  27. }
  28.  
This uses three "CounterX" <div> elements as containers, each of them counting up to 50, one starting 250ms after the other.
And (shockingly) this work in all my browsers except IE.

Any input would be greatly appreciated.

Thanks,
- Atli Þór
Oct 11 '08 #1
3 3007
rnd me
427 Expert 256MB
you should not have to use eval at all.

you need to use "var" before defining the function, rather than evaling it as a global.

also, "self" is a reserved word, replace it with "that".
Oct 11 '08 #2
Atli
5,058 Expert 4TB
Thank you for that.

I didn't realize "self" was reserved in JavaScript, but you are right, it appears to be a shortcut to "window".
Although, none of the browsers seem to have a problem with me redeclaring it.
In any case, I've change that now.

I don't really know what you mean by:
you need to use "var" before defining the function, rather than evaling it as a global.
I'm not sure what the "var" keyword has to do with defining functions. I thought it was only used with variables?

But, this had me do a little research on it, and I found out something interesting.

Until now, I thought that declaring a variable without the var keyword was equivalent to declaring it with it, with the exception that it could be explicitly deleted.

As it turns out, when I add the var keyword to the variable I previously called "self", it became unique to that instance! Which pretty much takes care of the problem for me.

Now I have this code, which works perfectly in all my browsers. (even IE!)
Expand|Select|Wrap|Line Numbers
  1. function Updater(pTargetElement, pMaxValue)
  2. {
  3.     this.targetElement = pTargetElement;
  4.     this.maxValue = pMaxValue;
  5.  
  6.     this.Start = function(pDelay)
  7.     {
  8.         var _this = this;
  9.         window.setTimeout(function(){
  10.             _this.update(0);
  11.         }, pDelay);
  12.     }
  13.  
  14.     this.update = function(pCurrent)
  15.     {
  16.         if (pCurrent >= this.maxValue) {
  17.             return;
  18.         }
  19.         ++pCurrent;
  20.         this.targetElement.innerHTML = pCurrent.toString();
  21.  
  22.         var _this = this;
  23.         window.setTimeout(function(){
  24.             _this.update(pCurrent);
  25.         }, 50);
  26.     }
  27. }
  28.  
  29. function bodyOnLoad()
  30. {
  31.     for (i = 1; i <= 3; i++) {
  32.         updater = new Updater(document.getElementById("Counter" + i.toString()), 50);
  33.         updater.Start(i * 250);
  34.     }
  35. }
  36.  
Thank you for the help. I would probably never have thought to look into that if you hadn't mentioned it :)
Oct 11 '08 #3
rnd me
427 Expert 256MB
Thank you for that.
Until now, I thought that declaring a variable without the var keyword was equivalent to declaring it with it, with the exception that it could be explicitly deleted.

As it turns out, when I add the var keyword to the variable I previously called "self", it became unique to that instance! Which pretty much takes care of the problem for me.

Thank you for the help. I would probably never have thought to look into that if you hadn't mentioned it :)
using var inside a function creates a local instance variable.

what i was getting at is that eval can screw with the scope, and you were clobbering a global version of the function with every eval.

using the function expression instead of eval is going to be a lot faster, simpler, and more reliable.

one tip: put 'var _this = this;' at the top of the constructor, and avoid repetition in sub functions. this could reduce memory usage slightly as well.

i probably should have been a little more specific, but i'm glad you go it working and learned a little bit.


the code in the second looks a lot nicer than the first.

cheers
Oct 11 '08 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

28
by: Daniel | last post by:
Hello =) I have an object which contains a method that should execute every x ms. I can use setInterval inside the object construct like this - self.setInterval('ObjectName.methodName()',...
9
by: Kelly Vernon | last post by:
I have a standard ASP page that appends to an xml page. Currently if there is more than one person attempting to append to the same XML file at a time. One user will have the ability to append,...
12
by: (Pete Cresswell) | last post by:
I know I can open many instances of a given form, but I've never done it. Now I'm analyzing an application where that seems like just the ticket: Many investment funds, *lots* of data points for...
1
by: Johan | last post by:
If a user happens to open multiple instances of her frontend, what kind of problems can occur? For example, one user reported that she was able to, once or twice, bypass the evaluation...
6
by: Bugs | last post by:
Does anyone have any recommendations on the best way to create multiple instances of the same class when the final number of instances is unknown? For example, I have a class and based on some...
17
by: Arjen | last post by:
Hi, I want to reload 2 divs at one click. Ive tried: <a href = "javascript:void(0);"...
3
by: Marcin Kalicinski | last post by:
How do I use multiple Python interpreters within the same process? I know there's a function Py_NewInterpreter. However, how do I use functions like Py_RunString etc. with it? They don't take any...
10
by: Pramod | last post by:
Hello to all of you, I want to know that what's the use to create static object. Thanks You Pramod Sahgal
4
by: yadin | last post by:
class big(self): x = 32 list = def inside (self): class small(self): # a new class defined inside the first y = 348 list.append(y) # send the value to first list
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.