PositiveGuy
PositiveGuy

Reputation: 47743

Scope of JavaScript Variables

Is it possible to define some global variables above your functions on the same .html page?

    <script type="text/javascript">

        birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
        birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
        birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');

        function ValidateCardField(validator, args)
        {
            if (args.Value.length > 0)
                args.IsValid = true;
            else
                args.IsValid = false;
        }
...

I'm getting nulls for the variable values.

Upvotes: 1

Views: 438

Answers (8)

Mike Blandford
Mike Blandford

Reputation: 4012

If you're unsure about this kind of thing, you can write up a quick test program and test it.

<html><head>
<script type="text/javascript">
var x = document.getElementById("bob");

function helloWorld(){
    alert(x == null);
}
</script>
</head>
<body onload="javascript:helloWorld();">
<div id="bob">hello back!</div>
</body>
</html>

Upvotes: 0

user182460
user182460

Reputation:

I think the problem is not related to the scope of variables, but to when you try to assign them with references to some page elements. Probably the script is running before all the page elements have been loaded. So the getElementById function will fail when trying to find an element that does not exist. Wrap your script in the onLoad event of the window object, like this:

window.onload = function () (
     // Your code here ...
);

Upvotes: 0

harto
harto

Reputation: 90483

The issue isn't one of scoping, but one of execution order. In your original implementation, the DOM elements aren't retrieved until the function is fired. Now, the elements are looked-up as soon as the JavaScript is parsed, which is presumably before the document (and hence, the elements) are loaded - hence they are null when the function is invoked.

Upvotes: 1

meder omuraliev
meder omuraliev

Reputation: 186562

Yes, it's possible to declare global variables but they are within the same namespace as the function definitions, if the variables are not defined in the function bodies and accessed inside, they descend upwards and reach the global/outer scope variables and use those.

OP - you should try moving your <script> block to right before the end body tag, that or adopt a domready/onload function.

Upvotes: 1

Sixten Otto
Sixten Otto

Reputation: 14816

Your problem may be that the script is being executed before the DOM has been fully initialized. So when these lines of code run:

    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');

no elements with those IDs exist yet, as far as the browser is concerned. One way to fix that would be to declare the variables as null, and then initialize them in a function that you call in the page's (client-side!) load handler.

It's probably also worth checking (by viewing the source in your browser) that those ClientID values are what you think they are, and that elements with those IDs really do exist in the rendered HTML.

Upvotes: 2

Jonathan Fingland
Jonathan Fingland

Reputation: 57167

EDIT

I see what the problem is. The DOM hasn't completely loaded when you're calling those in the global context (when it was called from the function, the DOM had already loaded).

In this case, you are probably best off using a framework like jQuery or Prototype.

See http://docs.jquery.com/Events/ready for running code after the DOM is loaded in jQuery and http://www.prototypejs.org/api/document/observe for prototype

e.g. in jQuery:

 $(document).ready(function () {
    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
 });

and in Prototype:

 document.observe("dom:loaded", function() {
    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
 });

Upvotes: 1

Josh Stodola
Josh Stodola

Reputation: 82483

Yes it is possible to have global variables, and you seem to be doing it correctly (although you should probably be using the var keyword to define them). The problem you are currently facing is that you are trying to access elements in the DOM before they have been rendered. What you need to do is define your variables globally, and then wait for the page to load before assigning them to the appropriate DOM elements...

var birthYear, birthMonth, birthDay;

window.onload = function() {
  birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
  birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
  birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
}

Now the variables will be globally accessible after the page loads.

Upvotes: 3

Alex Martelli
Alex Martelli

Reputation: 881555

The var keyword in Javascript means those variables are not global (global being unfortunately the default) but function-scoped -- not much point in using var outside of any function's scope (and potentially confusing), though it's legal. But the beauty of var and function scopes is to allow you to define rich closures, one of the truly beautiful aspects of Javascript -- i.e., if you example code is defined inside some outer function, and the outerfunction returns ValidateCardField or an object having the latter as one of its value, that inner function will get to access the non-global variables defined in its outer function, while the rest of the world is shielded off from them -- a much better way to do "private fields" than the Java/C++ approach of private as a keyword...!

Upvotes: 1

Related Questions