Что не так с определением переменных JavaScript внутри блоков if? - PullRequest
12 голосов
/ 22 июля 2009

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

if (condition) {
var variable = blah;
}

if (differentcondition) {
var variable = blah;
}

Это правильно?

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

JSLint продолжает говорить мне, переменная уже определена.

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

Спасибо.

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

$("#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 класса не являются взаимоисключающими.

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

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

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

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

Мне, наверное, следовало использовать этот пример с самого начала.

Ответы [ 5 ]

32 голосов
/ 22 июля 2009

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

Помещение переменной var в оператор if не противоречит «правилам» языка, но это означает, что из-за подъема var этот var будет определен независимо от того, выполнено ли условие оператора if.

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

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

12 голосов
/ 22 июля 2009

Это потому, что в JavaScript переменные имеют различную область видимости внутри функциональных блоков. В отличие от других языков, if-блоки не имеют другой области видимости в 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);
}
6 голосов
/ 22 июля 2009

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

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

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

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

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

$("#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
        }

});
0 голосов
/ 04 декабря 2016

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

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

$("#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
    }
});
0 голосов
/ 22 июля 2009

Являются ли два условия 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...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...