声明没有var关键字和逻辑OR的变量

时间:2011-08-10 15:09:43

标签: javascript

在声明具有逻辑OR的对象时,我得到一种奇怪的行为。

my_var = my_var || {}; // throws TypeError

如果我添加var关键字

var my_var = my_var || {}; // returns empty object

这是为什么?我似乎无法找到解释。 my_var是全局范围,为什么var会改变行为?

7 个答案:

答案 0 :(得分:5)

第一个示例尝试通过读取名为my_var的标识符(或空对象)中的值来分配名为my_var的全局对象上的属性。但是,标识符my_var在此时未定义,因此失败。

在第二个例子中,由于javascript变量提升的工作方式,my_var变量已经被声明,当你通过赋值来读取它时。

另请看这个例子:

a = a; // fails, undeclared identifier
a = 0;

使用var关键字,它将起作用!

b = b; // succeeds allthough identifier undeclared?!
var b = 0;

这是因为变量提升将把它变成这个:

var b; // declaration of b hoisted to the top of scope
b = b;
b = 0;

答案 1 :(得分:1)

在第二个示例中,var定义了my_var的范围。这允许正确设置值。以下是两个例子中发生的事情的快速而肮脏的看法:

使用示例1,JS引擎必须执行以下操作:

  1. 检查当前范围以查看是否存在my_var
  2. 检查上面的范围(以及上面的范围),直到找到my_var
  3. 如果找不到,请在全局范围内创建my_var。*
  4. *当您尝试将值分配给my_var时,尚未执行步骤3。

    示例2:

    1. 当前范围内是否有名为my_var的变量?是的,您刚刚使用var关键字创建了它。
    2. 分配其值。

答案 2 :(得分:1)

在定义没有var的变量时,您将直接访问global object。这意味着,如果您在浏览器中,您的Javascript引擎会尝试在全局对象(my_var)上查找window。由于该属性尚不存在,您的JS引擎将抛出。

当您的引擎尝试读取名为my_var的变量时,会在语句的右侧上发生这种情况。分配如

my_var = {};

会工作。但是访问没有var的标识符会导致浏览器查找scopechain。由于全局对象的variable object是全局对象本身,因此查找过程将无处可寻(=异常)。

通过将var关键字置于前面,您的js引擎在分析时知道它必须使用该标识符名称声明一个新变量。它实际上确实声明了具有undefined值的变量(称为“提升”)。这意味着,使用var将过早地在current context中创建具有该名称的属性。因此,如果该代码不在任何函数或eval上下文中,它将在my_var对象上创建属性window

答案 3 :(得分:0)

在第二种情况下,我的var未定义,因此为变量分配了一个空对象{}

答案 4 :(得分:0)

虽然我不能引用这些规范,但我认为var语句中的初始化只是语法糖:

var my_var = my_var || {};

相当于:

var my_var;
my_var = my_var || {};

在第一行中,my_var被声明并隐含地设置为特殊值undefined。然后,在第二行中,my_var存在,undefined评估为false,并且不会出现错误。

然而,在第一个示例中,当评估右侧时,my_var是未知的,因此是错误。

答案 5 :(得分:0)

在第一种情况下,您尝试分配未定义的变量。它和你写的一样:

my_var = a || {}; 

在第二种情况下,my_var只是未定义的,因为在实际范围内使用var关键字和create my_var。未定义转换为false,它将返回空对象。

答案 6 :(得分:0)

有趣的是,这个工作:

a = my_var || {}; // 'a' is now an empty object

当你使用'var'关键字时,你实际上给出了命令“创建一个新变量并为其赋值”。如果你不使用'var',那么你暗示变量已经存在于某个地方的全局范围内。

在您的示例中,JavaScript引擎尝试查找“my_var”的当前值,发现它不存在,无法创建它,因为您当前正在尝试为其分配值,并且失败。