Подтвердить что ты не робот

Что не так с определением переменных JavaScript внутри блоков if?

У меня есть такой код:

if (condition) {
var variable = blah;
}

if (differentcondition) {
var variable = blah;
}

Правильно ли это?

Я предполагаю, что переменная не будет назначена, если условие не вернет true.

JSLint продолжает рассказывать мне, уже определенную переменную.

Я делаю это неправильно?

Спасибо.

ОК, Здесь мой фактический usecase, я делаю делегирование событий следующим образом:

$("#container").click(function (event){ 

    if ($(event.target).is('img.class1')) {
        var imagesrc = $(event.target).attr('src');
        // Do something with imagesrc
    }

    if ($(event.target).is('img.class2')) {
        var imagesrc = $(event.target).attr('src');
        // Do something with imagesrc
    }

    // This condition is mutually exclusive to the above 2
    if ($(event.target).is('img.class3')) {
        var imagesrc = $(event.target).attr('src');
        // Do something with imagesrc
    }

    // This condition is mutually exclusive to 1 and 2 but not to 3
    if ($(event.target).is('img.class4')) {
        var imagesrc = $(event.target).attr('src');
        // Do something with imagesrc
    }

});

На самом деле эти 2 класса не являются взаимоисключающими.

Это работает для меня, но правильно ли это?

Ответы были очень информативными, но я до сих пор не понимаю, как мне здесь создавать переменные.

Собственно, я также хочу сказать, что некоторые условия являются взаимоисключающими, а некоторые условия не являются.

Как мне это структурировать?

Вероятно, я должен был использовать этот пример с самого начала.

4b9b3361

Ответ 1

Поскольку у javascript есть что-то, называемое "Подъем", которое заставляет ваш код делать что-то, похожее на то, что он должен делать. В основном это означает, что интерпретатор javascript будет перемещать все объявления var, независимо от того, где они находятся в теле функции, в верхней части тела функции. Затем он переместит все определения функций в начало, как раз под все вары. Затем он завершит компиляцию функции.

Включение var внутри оператора if не противоречит "правилам" языка, но это означает, что из-за перетаскивания var этот var будет определен независимо от того, выполняется ли условие оператора if.

Имейте в виду также, что подъем не включает назначение, так как другие указали, объявления var будут перемещены в начало и останутся undefined, пока они не будут назначены позже.

Это пример функции, которая должна была казаться хорошей идеей в то время, но она оказалась более запутанной, чем полезной.

Ответ 2

Это связано с тем, что в JavaScript переменные имеют только разную область действия внутри функциональных блоков. В отличие от других языков, if-blocks не имеют разной сферы в JavaScript.

В вашем случае JSLint скажет вам, что переменная уже определена, потому что возможно, что оба условия верны, и в этом случае вы переписываете свои переменные.

Вот пример того, как области работают в JavaScript:

function Something() {
    var thing1 = "hello";

    (function() {
        var thing2 = "world";
    })();

    // This line will throw a ReferenceError because "thing2" is not defined in this scope
    // It only exists within the scope of the function executed above
    alert(thing1 + thing2);
}

function SomethingElse() {
    var thing1 = "hello";

    if(true) {
        var thing2 = "world";
    }

    // This line will work because thing2 is not limited to the if-block
    alert(thing1 + thing2);
}

Ответ 3

Только функции создают внутреннюю область. Он становится еще более грубым, как в этом примере.

var x = 2;
function foo() {
    alert(x); // will alert undefined?!?

    var x = 4;
}
foo();
alert(x); // will alert 2

В первом предупреждении будет сказано undefined. Зачем? Поскольку все инициализации переменной, которые происходят в функции, инициализируются до undefined в начале функции. Вот почему Крокфорд говорит, чтобы как можно раньше инициализировать все переменные.

Итак, ваш код должен выглядеть примерно так:

$("#container").click(function (event){ 
        var imagesrc;
        if ($(event.target).is('img.class1')) {
                imagesrc = $(event.target).attr('src');
                // Do something with imagesrc
        }

        if ($(event.target).is('img.class2')) {
                imagesrc = $(event.target).attr('src');
                // Do something with imagesrc
        }

        // This condition is mutually exclusive to the above 2
        if ($(event.target).is('img.class3')) {
                imagesrc = $(event.target).attr('src');
                // Do something with imagesrc
        }

        // This condition is mutually exclusive to 1 and 2 but not to 3
        if ($(event.target).is('img.class4')) {
                imagesrc = $(event.target).attr('src');
                // Do something with imagesrc
        }

});

Ответ 4

Являются ли два взаимоисключающих условия if? Возможно, вы хотите использовать структуру управления "else":

if (condition) {
    var variable = blah;
}
else if (differentcondition) {
    var variable = blah;
}

Это означает, что если первое условие истинно, то вторая часть кода никогда не будет выполнена.

В общем, лучше объявить переменные в структуре, в которой они используются. Если переменная должна существовать только в выражении if, объявив ее там, она будет прекрасной, в противном случае переместите ее так:

var variable;
if (condition) {
    variable = blah;
}
else if (differentcondition) {
    variable = blah;
}
// continue to use variable here...

Примечание. Если вы используете отдельные ifs без else, тогда вам нужно сначала установить значение переменной по умолчанию.

Ответ 5

Как мне это структурировать?

В этом случае, похоже, было бы лучше вложить условия:

$("#container").click(function (event) {
    if ($(event.target).is('img')) {
        var imagesrc = $(event.target).attr('src');

        if ($(event.target).is('.class1')) {
            // Do something with imagesrc
        }

        if ($(event.target).is('.class2')) {
            // Do something with imagesrc
        }

        // This condition is mutually exclusive to the above 2
        if ($(event.target).is('.class3')) {
            // Do something with imagesrc
        }

        // This condition is mutually exclusive to 1 and 2 but not to 3
        if ($(event.target).is('.class4')) {
            // Do something with imagesrc
        }
    }
});

Или еще лучше использовать делегирование событий jQuery:

$("#container").on("click", "img", function (event) {
    var imagesrc = $(this).attr('src');

    if ($(this).is('.class1')) {
        // Do something with imagesrc
    }

    if ($(this).is('.class2')) {
        // Do something with imagesrc
    }

    // This condition is mutually exclusive to the above 2
    if ($(this).is('.class3')) {
        // Do something with imagesrc
    }

    // This condition is mutually exclusive to 1 and 2 but not to 3
    if ($(this).is('img.class4')) {
        // Do something with imagesrc
    }
});