在声明具有逻辑OR的对象时,我得到一种奇怪的行为。
my_var = my_var || {}; // throws TypeError
如果我添加var
关键字
var my_var = my_var || {}; // returns empty object
这是为什么?我似乎无法找到解释。 my_var
是全局范围,为什么var
会改变行为?
答案 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引擎必须执行以下操作:
my_var
。my_var
。my_var
。* *当您尝试将值分配给my_var
时,尚未执行步骤3。
示例2:
my_var
的变量?是的,您刚刚使用var
关键字创建了它。答案 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”的当前值,发现它不存在,无法创建它,因为您当前正在尝试为其分配值,并且失败。