Что не так с определением переменных 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 класса не являются взаимоисключающими.
Это работает для меня, но правильно ли это?
Ответы были очень информативными, но я до сих пор не понимаю, как мне здесь создавать переменные.
Собственно, я также хочу сказать, что некоторые условия являются взаимоисключающими, а некоторые условия не являются.
Как мне это структурировать?
Вероятно, я должен был использовать этот пример с самого начала.
Ответы
Ответ 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
}
});