Skip to main content

var x = x || "default val” not getting set properly if x is defined above it


HTML:




<script type="text/javascript">
var x = "overriden";
</script>
<script src="myjs.js"></script>



myjs.js:




$(document).ready(function(){
var x = x || "default val";
alert(x); // this alerts "default val" and not "overriden"
});



For some reason, x is ending up as "default val" and not "overriden" , even tho initially I'm setting it to "overriden" before I even include the script reference to myjs.js.



Any idea as to why this is happening? I'm trying to enable the hosting page to set an override for a variable that's used in an included js file, otherwise use the default val.


Source: Tips4allCCNA FINAL EXAM

Comments

  1. What you have after variable declaration hoisting is applied:

    var x;
    x = 5;

    $(document).ready(function(){
    var x;
    x = x || "default";
    });


    It looks at the closest x and sees it's value is undefined which is a falsy value, so x gets set to "default".

    You would be fine if they were in the same scope, because the declarations are always hoisted above assignments so:

    var x = 5;

    var x = x || "default";


    Is actually just

    var x;

    x = 5;
    x = x || "default";




    This was suggested which is completely pointless:

    $(document).ready(function(){
    x = x || "default";
    });


    It will throw a ReferenceError if x is not defined.

    So either do the check in the same scope or do something like:

    $(document).ready(function(){
    var x = window.x || "default";
    });


    Invalid property reads don't cause a ReferenceError but just return undefined instead.

    ReplyDelete
  2. The var x in the function passed to $(document).ready() is hiding the global scope x variable.

    If you just use x = x || "default val";, then the global variable is clobbered. However, it's really a bad idea to have global variables at all.

    ReplyDelete
  3. You are using the var keyword in both places. Try:

    x = x || "default val";


    https://developer.mozilla.org/en/JavaScript/Reference/Statements/var

    From the above link:


    The scope of a variable declared with var is the enclosing function
    or, for variables declared outside a function, the global scope (which
    is bound to the global object).

    ReplyDelete
  4. x is not defined in the scope of the document ready function.

    var x is preparing the variable with the value undefined, so it won't get it from the window scope.

    Try var x = x || window.x || "default val"; instead.

    ReplyDelete
  5. Since you have it stated with a var that does not get the globally defined object from the html. Try removing the var and see if you get a different result, or change the variable within the function to a different letter.

    When you use var within a function the scope of that var is only to the function. Since you have defined the x variable twice when you are doing the comparison it is attempting to use the variable from within the function.

    If you plan to keep the var statement you will need to change the variable name or how you are calling the global x to window.x. The other option is just to drop the var from the function.

    ReplyDelete
  6. The x created on this line:

    var x = x || "default val";


    ...is local to the function it is defined in (i.e. it shadows the global x) .

    Removing the preceding var will cause both x names to reference the same global variable, but this is generally a bad idea. From the previously-linked Wikipedia page:


    This can lead to confusion, as it may be unclear which variable
    subsequent uses of the shadowed variable name refer to.

    ReplyDelete
  7. Because you are again declaring a new var x inside document.ready() which is another scope than global. Try this

    $(document).ready(function(){
    x = x || "default val";
    alert(x); // this will now alert "overriden"
    });

    ReplyDelete
  8. You are declaring var x in your function which creates local storage for x and hides previous values.

    Call it var y, or do as karim79 suggested.

    ReplyDelete
  9. Your var x in the second one is local to that function, and isn't the same as window.x (which is what you've defined in the former block).

    ReplyDelete
  10. the keyword var means that you've just created a local variable. So basically what is happening is that:


    You declare (in your first block ) x as "overridden"


    Memory:

    x -> "overriden"



    You set the callback to document.ready


    Memory:

    x -> "overriden"


    (after the document is loaded) 3. you run your anonymous function, initialising x with var

    Memory:

    x->"overriden"
    [IN SCOPE]
    anonymous_function.x -> "default_value"
    [/SCOPE]




    "BUT WAIT", you might say, "the code I wrote is var x= x || "default var" so what should happen is local_x=global_x || "default value ,right?

    Unfourtunately Javascript doesn't work like that. In javascript, we have function scope, instead of the more widely used block scope. So when you write:

    f=function(){
    var x=y || "default value";
    var y=3;
    alert(x);
    }


    what'll be interpreted in javascript is :

    f=function(){
    var x;
    var y;
    x=y || "default value";
    y=3;
    alert(x);
    }


    so running y=10; f(); will give you "default value" on the prompt.



    So taking off your var will work to fix your problem here, but just remember in general that all your variable declarations are done "at the beginning" of a function, so scope is immediately changed when entering a function.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex