简体   繁体   中英

scoping and hoisting for variables declared in if else block in javascript

i implemented click event on a input:checkbox .inside the addEventListener method i have a if-else block .As javascript has only function and global scope, not if-else block scope.So a variable declared inside if block should be accessible inside else block also.But here the variable "all_disabled" is causing error inside else condition.It says "cant read property length of undefined"

according to my understanding : all_disabled should be hoisted at the top of function scope ( it is now undefined ).After first click to checkbox ( make it checked ) it should be defined.So,when it goes to else (uncheck it ) it shouldn't be undefined

Why is it behaving like this?Or do i have any misconception about scoping in JS?

document.getElementById('show_hidden').addEventListener('click',function(event){

        if(this.checked){
            $('#hidden_image').show("slow");
            var all_disabled=document.getElementsByClassName('all_disabled');
            for(i=0;i<all_disabled.length;i++){

                if(all_disabled[i].disabled==true){

                    all_disabled[i].disabled=false;

                }
            }

        }else{
            $('#hidden_image').hide();
            for(i=0;i<all_disabled.length;i++){

                all_disabled[i].disabled=true; // error is here 

            }
        }
});

When the decision goes into the else branch, the all_disabled variable is undefined. Why? Because the only place where it is defined is inside the other branch.

Try moving its definition outside the if..else

document.getElementById('show_hidden').addEventListener('click',function(event){

        var all_disabled=document.getElementsByClassName('all_disabled');

        if(this.checked){
            $('#hidden_image').show("slow");

            for(i=0;i<all_disabled.length;i++){

                if(all_disabled[i].disabled==true){

                    all_disabled[i].disabled=false;

                }
            }

        }else{
            $('#hidden_image').hide();
            for(i=0;i<all_disabled.length;i++){

                all_disabled[i].disabled=true;

            }
        }
});

I think you are having right concept of scope but wrong concept of Javascript, for this to work the code must be executed at least once before . Since it has never been run before in its entire life time , the variable reference remains undefined . Which is why you are getting those error messages . So as to say that , in a normal conversation between two people , Person A starts Talking about "Ankle Tap" , (a method of defence in rugby) , Person B is not aware of what an "Ankle Tap" is since he has never seen or played Rugby before. Since it was not immediately defined by person A . Person B seems to find it odd.

Same case here , the reference of all_disabled according to else statement is not defined , but according to if statement well defined . I hope this clears your confusion.

R. Schifini's answer explains the problem in your code well. I'd just like to mention something else.

Since you are using jQuery in part of your code, you may as well use jQuery for all the DOM manipulation. This will simplify your code quite a bit:

$('#show_hidden').on( 'click', function() {
    if( this.checked ) {
        $('#hidden_image').show( 'slow' );
    } else {
        $('#hidden_image').hide();
    }
    $('.all_disabled').prop( 'disabled', ! this.checked );
});

No variables and no loops! Less code means less to go wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM