JavaScript的条件检查中的行为不一致

时间:2010-11-30 11:04:25

标签: javascript

我想用属性obj1构建一个对象obj2,这是另一个对象。为避免重新声明obj1obj2,我使用以下代码:

if (!obj1) obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
// code to use obj1

假设,obj1obj1.obj2尚未定义,代码会导致浏览器报告错误“obj1未定义”。

如果我将代码更改为:

if (typeof obj1==='undefined') obj1 = {};
if (!obj1.obj2) obj1.obj2 = {};
// code to use obj1

然后没有错误,而我认为它应该报告“obj2未定义”。我很困惑为什么JavaScript会对参考和属性的短手错误检查进行不同的处理。任何人都可以对此有所了解吗?

4 个答案:

答案 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

  
      
  1. 如果Type(V)不是Reference,则返回V。
  2.   
  3. 让base成为调用GetBase(V)的结果。如果
  4.   
  5. IsUnresolvableReference(V),抛出一个   ReferenceError异常。
  6.   
  7. 如果   IsPropertyReference(V),然后
  8.         
        

    一个。如果     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

希望这有帮助