Variable shadowing and testing for existence before assignment in javascript

Deadly 提交于 2019-12-10 17:14:36

问题


In the following code snippet I declare a global variable and then check for its presence inside a function.

<script>
x = 5;
$(function() {
   var x = x || 3;
   console.log(x); // prints 3
});
</script>

This behaves differently:

<script>
x = 5;
$(function() {
   var y = x || 3;
   console.log(y); // prints 5
});
</script>

I expect that in the first example, the variable declaration in the inner scope will detect that x already exists in the global scope, and take its value. Why does the first example 3?

Specifically I recently wrote some code that checks var _gaq = _gaq || [] in a jQuery ready scope and was confused when nothing was getting pubbed to Analytics.


回答1:


You're looking for x in the wrong scope. Due to variable hoisting, var x has actually defined a local x variable with a value of undefined before your x || 3 check happens:

var x = x || 3;

is actually:

var x = undefined;
x = x || 3;

Simply change it to look for x on the window object:

var x = window.x || 3;



回答2:


The first example logs 3 because any variable that is initialized inside a function using the var keyword will have a local scope. If a variable is initialized inside a function without var, it will have a global scope.

So in the first case, when the local x is assigned, since it is uninitialized, it gets assigned 3.

While in the second case, x refers to the global variable x as there is no declaration of x inside the function.

Instead, if you try this

<script>
x = 5;
$(function() {
   x = x || 3;
   console.log(x);
});
</script>

OR

<script>
x = 5;
$(function() {
   var x = window.x || 3;
   console.log(x);
});
</script>

you will get the expected result 5.

Additionally, unlike C and its family (which has block-level scope), JavaScript has function-level scope. Blocks, such as if statements, do not create a new scope. Only functions create a new scope.

So if I were to write something like

#include <stdio.h>
int main() {
    int x = 1;
    printf("%d, ", x); // 1
    if (1) {
        int x = 2;
        printf("%d, ", x); // 2
    }
    printf("%d\n", x); // 1
}

OUTPUT: 1,2,1

as compared to

var x = 1;
console.log(x); // 1
if (true) {
    var x = 2;
    console.log(x); // 2
}
console.log(x); // 2

OUTPUT: 1,2,2

Go through this excellent blog post on JavaScript Scoping and Hoisting to understand it better.




回答3:


The var x in the function declares x to be local to the function, so in x || 3 x not the global x and thus is undefined since it hasn't been initialized.

In var y = x || 3; x is the global x as there is no x local the function.



来源:https://stackoverflow.com/questions/11511242/variable-shadowing-and-testing-for-existence-before-assignment-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!