2

I have a minor problem with a JavaScript snippet that I hope you can help me solving it.

var z=0;

function xyz() { 
    if (!z) {
        z+=5;
        var h=15; // The problem resides here
    }
    else { 
        var f=h+7;
        alert(f);
         }
    z++;
    return z;    
}

When I registered this function to a click event handler on a button element, I was expecting to see by the second iteration of function execution an alert message displaying

22

What I had was a NaN message indicating that the variable h wasn't defined despite the explicit declaration statement within the if branch but when I omitted the var keyword, suddenly the function behaved :)

It's really puzzling for me as I am pretty sure that JS doesn't natively support block scoping except when using the let keyword introduced by Mozilla browsers. I am also darn sure that declaring variables using the var keyword creates local scope for them and therefore they become exclusively accessible within the function in which they are defined.

So, why on the world I have to declare h as a global variable for the function to work?

Any help would be very appreciated as I am new to Web Design and I am coming from graphic design background.

Note: Actually,this was not the real life problem that I faced during coding. I was trying to create a ticker that updates every 10 seconds automatically using the setInterval() method and then suppressing it when the user browses the headlines manually and when he's done, the script takes over once again.

I thought that a more generic and simple example is more suitable to explain the solution without getting into the details of the methods/properties used.

=======

UPDATE

I think I got it now. Functions don't have memories and thus can't remember values generated from previous calls. What I was doing actually is storing the value generated from the first call in a global variable that can be accessed in future calls. But I'm wondering is there any elegant way to achieve the same result other than using global variables?

3 Answers 3

6

No. In fact all your local variables are initialized at the beginning of your function. Your example code will be executed like this:

function xyz() { 
    var h;
    var f;
    if (!z) {
        z+=5;
        h=15;
    }
    else { 
        f=h+7;
        alert(f);
         }
    z++;
    return z;    
}

You get NaN because in f=h+7 h is declared but it's value is undefined.

There is a more elegant way: using objects. There are may ways you can create objects, I use the most compact method here:

function MyObject() {
    this.z = 0;
    // it's safer to initialize all your variables (even if you dn't use the initial value)
    this.h = 0;
    this.f = 0;

    this.xyz = function () {
        if (!this.z) {
            this.z += 5;
            this.h = 15;
        } else { 
            this.f = this.h + 7;
            alert(this.f);
        }
        this.z++;
        return this.z;    
    }
}

var o = new MyObject();
o.xyz();
o.xyz();

There are many-many docs about OOP in JS if you are interested.

Sign up to request clarification or add additional context in comments.

9 Comments

Explanation for the OP: The value of h is undefined because the if-branch did not execute, so that the assignment h = 15 didn't occur.
@Sime> Actually the z variable is initialized and set to zero outside the function in the global scope. Since it's set to zero, the function must enter the first branch of the if statement in the first iteration.
@vbence Explain to me why it's working in the global scope and not the local one? Please note that the function must visit the 1st branch of the if statement and consequently overwriting the initial value of the variable z and declaring the h variable
@ادي عبد الهادي Each function call defines a new set of local variables. When the function is called for the 1. time, h is indeed set to 15. However, when the function is called for the 2. time, the h local variable is not set to 15 which means that its initial undefined value is used.
@Šime Vidas Thanks for your answer. I think I got it now. Functions don't have memories and thus can't remember values generated from previous calls. What I was doing actually is storing the value generated from the first call in a global variable that can be accessed in future calls. But I'm wondering is there any elegant way to achieve the same result other than using global variables?
|
1

Nope, only functions have a local scope. Do not put anything in global scope unless you absolutely have to.

2 Comments

@Šime_Vidas: @vbence gave a more detailed answer -- I just answer the question in the title.
Yes, you're right. The OP asks two different questions - one in the title and one in the question body. You answered on of those questions, which makes your answer valid.
0

You can use closures to get the result (I think) you want, e.g.

var xyz = (function() {
  var z = 0;
  var h;

  return function() { 
    var f;

    if (!z) {
      z += 5;
      h = 15;

    } else { 
      f = h + 7;
      alert(f);
    }
    return ++z;
  }
})();

the first time nothing is shown, after that 22 is always shown and z increments 6, 7, 8, and so on.

-- Rob

1 Comment

Thanks Rob for your valuable answer. It works like a charm but the concept of closures is bit advanced for me. Every time I read on the subject, I get frustrated but sooner or later I will manage to get my head around it. Just one simple question, do I have to initialize variables like you did with h and f for functions or it's okay to use them out of the box?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.