Clearing Variables in JavaScript

Hello, everybody. When I’m doing exercises in JavaScript, I often find that I need to run it with different values for a given variable, and I’m annoyed that it insists on “remembering” what x was in an earlier function, or an earlier version of my current function. How can I get JS to “forget” that earlier x, allowing me to use it as a blank slate?

You can set variables to null (or undefined) when you’re done with them, but what you’re talking about is a poor design strategy. Can you give an example of what you’re working on and maybe we can figure out a better way to structure your data?

Sure. Let’s say that I implement the following exercise to get a handle on eval(…). (I know, you’re not supposed to actually use it; it’s just an exercise, not a live program.)

function foo (str, a) {
    eval(str);
    console.log(a, b);
}
var b = 2
foo("var b = 3", 1)

Fine, so I get a “1 3” printed to the screen.

Now, I decide to run the same function, but a bit changed, like so:

function foo (str, a) {
    "use strict"
    eval(str);
    console.log(a, b);
}

foo("var b = 3", 1)

What I’m expecting to get is a reference error, since b is not defined in this version. What I actually get is “1 3”. Apparently JS is “remembering” the old value of b, instead of looking at the “current” value. How do I get rid of this behavior?

I cleaned up your code.
You need to use triple backticks to post code to the forum.
See this post for details.

What environment are you working in? Is this code you type directly into your browser console?

The short answer is that it’s not possible to manually destroy variables you create with a keyword (var). That’s up to the garbage collector, which is completely automated. I think the easiest solution for you is to wrap each code in an immediately invoked function expression. This is simply a function that runs immediately rather than being invoked later. It will create a context for each of your variables.

(function() { //create a new anonymous function, but put an opening paren in front of it
    function foo (str, a) {
        eval(str);
        console.log(a, b);
    }
    var b = 2
    foo("var b = 3", 1)
})() // Notice that the function gets closed off with another paren, and then there's
    // two more parentheses.  This is what invokes the function.

To generalize this, an IIFE (pronounced “iffy”) looks like this:

(function (parameters...) { /* code here */ })()

Sometimes you’ll see the invoking parentheses inside of the iffy:

(function (parameters...) { /* code here */ }())

This is a purely stylistic choice, but as with other stylistic choices, some programmers will literally murder you if you disagree with them.

1 Like

Thanks for the clean-up. I keep forgetting those back-ticks.

Yes, I’m just typing directly into the browser console.

So an IIFE will come closest to what I want to do? Terrific; thank you very much for your help. :bow:

As for murderous coders, I’ll just have to chance it.

This is a technique that will come in handy no matter where you’re writing code, by the way. It’s often used to keep code within a predictable context.

And when you hear or read programmers who say to “keep the global scope uncluttered”, or something, this problem you’re having is exactly why.

Glad I could help.

1 Like

in ES6 you can use the new let keyword instead of var to have a new variable only within the current scope. Here is an example from MDN:

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

I think this is probably a little easier and more readable than the traditional way @PortableStick mentioned.

1 Like

Very interesting. I’ll have to work with that a bit to get it to sink in; thanks for the info!

1 Like

In order for let to do anything in this case, the code will need to be wrapped in brackets, eg.

{
    function foo (str, a) {
        eval(str);
        console.log(a, b);
    }
    let b = 2
    foo("let b = 3", 1)
}

Also, it changes the outcome of that code, which may or may not matter, since eval is called within a new block scope. At least browser support is good now :thumbsup:

1 Like