在if块中定义JavaScript变量有什么问题?

时间:2021-01-30 00:06:04

I have some code like this:

我有一些像这样的代码:

if (condition) {
var variable = blah;
}

if (differentcondition) {
var variable = blah;
}

Is this correct?

它是否正确?

I assume that the variable wouldn't be assigned if the condition doesn't return true.

我假设如果条件不返回true,则不会分配变量。

JSLint keeps on telling me, variable already defined.

JSLint继续告诉我,变量已经定义。

Am I doing this wrong?

我做错了吗?

Thanks.

OK, Here's my actual usecase, i'm doing event delegation like this:

好的,这是我的实际用例,我正在做这样的事件委托:

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

});

Actually these 2 classes are not mutually exclusive.

实际上这两个类并不相互排斥。

This works for me, but is it correct?

这适用于我,但它是否正确?

The answers were very informative, but I still don't understand how I should set up the variables here.

答案非常有用,但我仍然不明白我应该如何在这里设置变量。

Actually I also want to say that certain conditions are mutually exclusive, and certain conditions are not.

实际上我也想说某些条件是相互排斥的,而某些条件则不是。

How should I structure this?

我应该如何构建这个?

I probably should've used this example from the beginning.

我可能应该从一开始就使用这个例子。

5 个解决方案

#1


Because javascript has something called "Hoisting" which makes your code do things it doesn't look like it should be doing. Basically, that means a javascript interpreter will move all var declarations, regardless of where they are in the body of a function, to the top of the function body. Then it will move all function definitions to the top, just under all the vars. Then it will finish compiling the function.

因为javascript有一些名为“Hoisting”的东西,它使你的代码做的事情看起来不像它应该做的那样。基本上,这意味着javascript解释器会将所有var声明(无论它们在函数体中的位置)移动到函数体的顶部。然后它会将所有函数定义移动到顶部,就在所有变量之下。然后它将完成编译功能。

Putting a var inside an if statement is not against "the rules" of the language, but it means that, because of var hoisting, that var will be defined regardless of whether the if statement's condition is satisfied.

将var放在if语句中并不违反语言的“规则”,但这意味着,由于var提升,无论if语句的条件是否满足,都将定义var。

Keep in mind also that hoisting does not include the assignment, so as others have pointed out, the var declarations will be moved to the top, and left undefined until they're assigned later.

还要记住,提升不包括赋值,正如其他人所指出的那样,var声明将被移动到顶部,并保持未定义,直到它们稍后被分配。

This is an example of a feature that must have seemed like a good idea at the time, but it has turned out to be more confusing than helpful.

这是一个当时看起来一个好主意的功能的例子,但事实证明它更令人困惑而不是有用。

#2


This is because in JavaScript, variables only have different scope within function blocks. Unlike other languages, if-blocks do not have a different scope in JavaScript.

这是因为在JavaScript中,变量在功能块中只有不同的范围。与其他语言不同,if-blocks在JavaScript中没有不同的范围。

In your case, JSLint would tell you the variable is already defined because it is possible that both conditions are true, in which case you'd be overwriting your variables.

在您的情况下,JSLint会告诉您变量已经定义,因为两个条件都可能为真,在这种情况下您将覆盖变量。

Here is an example of how scopes work in JavaScript:

以下是范围如何在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


Only functions create inner scope. It gets even hairier like in this example.

只有函数创建内部范围。它在这个例子中变得更加毛茸茸。

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

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

The first alert will actually say undefined. Why? Because all variable initializations that occur in the function get initialized to undefined at the start of the function. Which is why Crockford says to initialize all variables as early as possible.

第一个警报实际上会说未定义。为什么?因为函数中出现的所有变量初始化在函数开始时都被初始化为undefined。这就是为什么Crockford说要尽早初始化所有变量。

So your code should probably look like this:

所以你的代码可能看起来像这样:

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


Are the two if-conditions mutually exclusive? Perhaps you want to use the "else" control structure:

两个if条件是否相互排斥?也许你想使用“else”控制结构:

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

This means that if the first condition is true, then the second part of the code will never be executed.

这意味着如果第一个条件为真,那么代码的第二部分将永远不会被执行。

In general, it's better to declare variables within the structure they are being used in. If the variable should only exist within the if statement, declaring it there is fine, otherwise, move it outside like so:

一般来说,最好在它们正在使用的结构中声明变量。如果变量应该只存在于if语句中,则声明它没有问题,否则,将它移到外面就像这样:

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

Note: if you're using separate ifs without the else, then you'll need to set variable to a default value first.

注意:如果你在没有else的情况下使用单独的ifs,那么你需要先将变量设置为默认值。

#5


How should I structure this?

我应该如何构建这个?

In this case, it looks like it would be better to nest the conditions:

在这种情况下,看起来嵌套条件会更好:

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

Or better yet use jQuery's event delegation:

或者更好的是使用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
    }
});

#1


Because javascript has something called "Hoisting" which makes your code do things it doesn't look like it should be doing. Basically, that means a javascript interpreter will move all var declarations, regardless of where they are in the body of a function, to the top of the function body. Then it will move all function definitions to the top, just under all the vars. Then it will finish compiling the function.

因为javascript有一些名为“Hoisting”的东西,它使你的代码做的事情看起来不像它应该做的那样。基本上,这意味着javascript解释器会将所有var声明(无论它们在函数体中的位置)移动到函数体的顶部。然后它会将所有函数定义移动到顶部,就在所有变量之下。然后它将完成编译功能。

Putting a var inside an if statement is not against "the rules" of the language, but it means that, because of var hoisting, that var will be defined regardless of whether the if statement's condition is satisfied.

将var放在if语句中并不违反语言的“规则”,但这意味着,由于var提升,无论if语句的条件是否满足,都将定义var。

Keep in mind also that hoisting does not include the assignment, so as others have pointed out, the var declarations will be moved to the top, and left undefined until they're assigned later.

还要记住,提升不包括赋值,正如其他人所指出的那样,var声明将被移动到顶部,并保持未定义,直到它们稍后被分配。

This is an example of a feature that must have seemed like a good idea at the time, but it has turned out to be more confusing than helpful.

这是一个当时看起来一个好主意的功能的例子,但事实证明它更令人困惑而不是有用。

#2


This is because in JavaScript, variables only have different scope within function blocks. Unlike other languages, if-blocks do not have a different scope in JavaScript.

这是因为在JavaScript中,变量在功能块中只有不同的范围。与其他语言不同,if-blocks在JavaScript中没有不同的范围。

In your case, JSLint would tell you the variable is already defined because it is possible that both conditions are true, in which case you'd be overwriting your variables.

在您的情况下,JSLint会告诉您变量已经定义,因为两个条件都可能为真,在这种情况下您将覆盖变量。

Here is an example of how scopes work in JavaScript:

以下是范围如何在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


Only functions create inner scope. It gets even hairier like in this example.

只有函数创建内部范围。它在这个例子中变得更加毛茸茸。

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

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

The first alert will actually say undefined. Why? Because all variable initializations that occur in the function get initialized to undefined at the start of the function. Which is why Crockford says to initialize all variables as early as possible.

第一个警报实际上会说未定义。为什么?因为函数中出现的所有变量初始化在函数开始时都被初始化为undefined。这就是为什么Crockford说要尽早初始化所有变量。

So your code should probably look like this:

所以你的代码可能看起来像这样:

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


Are the two if-conditions mutually exclusive? Perhaps you want to use the "else" control structure:

两个if条件是否相互排斥?也许你想使用“else”控制结构:

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

This means that if the first condition is true, then the second part of the code will never be executed.

这意味着如果第一个条件为真,那么代码的第二部分将永远不会被执行。

In general, it's better to declare variables within the structure they are being used in. If the variable should only exist within the if statement, declaring it there is fine, otherwise, move it outside like so:

一般来说,最好在它们正在使用的结构中声明变量。如果变量应该只存在于if语句中,则声明它没有问题,否则,将它移到外面就像这样:

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

Note: if you're using separate ifs without the else, then you'll need to set variable to a default value first.

注意:如果你在没有else的情况下使用单独的ifs,那么你需要先将变量设置为默认值。

#5


How should I structure this?

我应该如何构建这个?

In this case, it looks like it would be better to nest the conditions:

在这种情况下,看起来嵌套条件会更好:

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

Or better yet use jQuery's event delegation:

或者更好的是使用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
    }
});