我想用属性obj1
构建一个对象obj2
,这是另一个对象。为避免重新声明obj1
和obj2
,我使用以下代码:
if (!obj1) obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
// code to use obj1
假设,obj1
和obj1.obj2
尚未定义,代码会导致浏览器报告错误“obj1未定义”。
如果我将代码更改为:
if (typeof obj1==='undefined') obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
// code to use obj1
然后没有错误,而我认为它应该报告“obj2未定义”。我很困惑为什么JavaScript会对参考和属性的短手错误检查进行不同的处理。任何人都可以对此有所了解吗?
答案 0 :(得分:6)
如果你愿意:
if (!window.obj1) window.obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
您会发现代码按预期工作。
当你检查它是否存在时, obj1
甚至都不是参考;没什么。它不存在,因为你还没有声明它(你没有初始化它)。
var obj1;
if (!obj1) obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
这也有效,因为你已宣布存在obj1
;你还没有初始化它。
尚未设置的对象的所有属性都包含值undefined
;这就是为什么它回应你的短手!obj1.obj2
var obj1 = {};
obj1.a === undefined // true;
但是,必须先定义变量,然后才能访问它们。
答案 1 :(得分:3)
我认为后一个代码归结为ECMAScript 5中的§8.7.1和§8.12.3:
8.7.1 GetValue
- 如果Type(V)不是Reference,则返回V。
- 让base成为调用GetBase(V)的结果。如果
- IsUnresolvableReference(V),抛出一个 ReferenceError异常。
- 如果 IsPropertyReference(V),然后
醇>一个。如果 HasPrimitiveBase(V)为false,然后让 得到[[Get]]的内部方法 基地,否则让我们变得特别 [[Get]]内部方法定义如下。
湾返回调用的结果 使用base作为其内部方法 这个价值,并通过 参数的GetReferencedName(V)。
5。否则,基地必须是一个环境 记录。
一个。返回结果 调用GetBindingValue(参见 10.2.1)基础传递GetReferencedName(V)和的基本方法 IsStrictReference(V)作为参数。
8.12.3 [[Get]]
当[[Get]]内部方法为O. 用属性名称P调用 采取以下步骤:
8。设desc是调用[[GetProperty]]内部方法的结果 O,财产名称为P.
9。如果desc是 undefined,返回undefined。
10如果 IsDataDescriptor(desc)为true,返回 描述第[[值]]。
11否则, IsAccessorDescriptor(desc)必须是 是的,让getter成为desc。[[Get]]。
12。如果getter未定义,请返回 未定义。
13。返回结果调用 getter的[[Call]]内部方法 提供O作为此值和 不提供任何论据。
正如您所看到的,它只为ReferenceError
抛出IsUnresolvableReference
。如果未定义基数(obj1),则适用。在§15.11.6.3中有一个引发ReferenceError的地方列表。
答案 2 :(得分:3)
根本没有声明“obj1”引用,因此会出错。
使用以下语法进行此类检查:
var obj1 = obj1 || {};
顺便说一下:
if (typeof obj1==='undefined') obj1 = {};
如果obj1 == null,无效。
不要声明全局变量(不带var)。 我强烈建议您阅读JavaScript:The Definitive Guide,5th Edition。 你可以跳过一些章节,但要注意第3章,第7章,第8章,第9章。必须阅读并理解它们。
答案 3 :(得分:0)
我尝试使用chrome JScript控制台重建它
如果你在两行之前都没有定义obj1和obj1.obj2的监视表达式:
obj1: ReferenceError: obj1 is not defined
obj1.obj2: ReferenceError: obj1 is not defined
一旦你越过这条线 if (typeof obj1==='undefined') obj1 = {};
,他们就会变成
obj1: Object
obj1.obj2: undefined
因此,您无法使用!
检查第一个,因为它不是undefined
希望这有帮助