a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 278|回复: 1

[专业语言] JAVA认证:如何判断JavaScript对象是否存在

[复制链接]
发表于 2012-8-4 12:44:44 | 显示全部楼层 |阅读模式
判断一个Javascript对象是否存在的方法有很多,然而只有对Javascript语言的实现细节非常清楚,才可能分得清它们的区别。下面我们一起来了解一下判断JavaScript对象是否存在的10个方法。! \/ A0 @& s( d. _
    Javascript语言的设计不够严谨,很多地方一不小心就会出错。
: z6 s  x2 d  w5 g" f9 x; e7 ]; A    举例来说,请考虑以下情况。
  e5 N- C: S: [- i* J) v    现在,我们要判断一个全局对象myObj是否存在,如果不存在,就对它进行声明。用自然语言描述的算法如下:6 t/ s3 u; H, n: X# o, G
    if (myObj不存在){  声明myObj;  }$ b* `, D4 K& Z/ W: j# h
    你可能会觉得,写出这段代码很容易。但是实际上,它涉及的语法问题,远比我们想象的复杂。Juriy Zaytsev指出,判断一个Javascript对象是否存在,有超过50种写法。只有对Javascript语言的实现细节非常清楚,才可能分得清它们的区别。
. `1 Z6 l" L) L: K7 J& I    第一种写法: s  ]9 i, ^+ ^6 A" k$ V
    根据直觉,你可能觉得可以这样写:
. A! P; r8 H9 L2 _    if (!myObj)& Z# G& e/ _# _6 K) F
    {  myObj = { };  }- k, d% s$ `: m
    但是,运行这段代码,浏览器会直接抛出ReferenceError错误,导致运行中断。请问错在哪里?  y& _6 k2 T3 ~. l& Z3 [
    对了,if语句判断myObj是否为空时,这个变量还不存在,所以才会报错。改成下面这样,就能正确运行了。
% x, \7 p2 H: ~2 Z    if (!myObj)3 x" E8 o+ h9 B, [; X) u; z
    {  var myObj = { };  }
& L! O2 N" _* [3 @% j# q    为什么加了一个var以后,就不报错了?难道这种情况下,if语句做判断时,myObj就已经存在了吗?) V, V4 l# x& R5 v! L( V  w
    要回答这个问题,就必须知道Javascript解释器的工作方式。Javascript语言是"先解析,后运行",解析时就已经完成了变量声明,所以上面的代码实际等同于:% t$ ?1 g* W& x  y! H% h
    var myObj;  if (!myObj)
8 \& |9 J+ m3 [    {  var myObj = { };  }
; m6 s/ v$ ]; y* ]6 V    因此,if语句做判断时,myObj确实已经存在了,所以就不报错了。这就是var命令的"代码提升"(hoisting)作用。Javascript解释器,只"提升"var命令定义的变量,对不使用var命令、直接赋值的变量不起作用,这就是为什么不加var会报错的原因。5 h1 L' L0 V. b) b
    第二种写法# B# X0 S2 i' ~9 V5 ~- p
    除了var命令,还可以有另一种改写,也能得到正确的结果:
6 u( }7 C+ b; l" m% K3 z- U    if (!window.myObj)( ^" b1 J  _8 K! H& A+ e0 S& O
    {  myObj = { };  }6 o& r/ {- C  G. _
    window是javascript的顶层对象,所有的全局变量都是它的属性。所以,判断myobj是否为空,等同于判断window对象是否有myobj属性,这样就可以避免因为myObj没有定义而出现ReferenceError错误。不过,从代码的规范性考虑,最好还是对第二行加上var:
& W& A+ A) `# ^    if (!window.myObj)3 k3 U2 k" U' b4 j& S/ a
    {  var myObj = { };  }
9 d. N9 x1 \$ _9 z' \, v2 V    或者写成这样:
; G: y  e& ?3 @4 k) ?    if (!window.myObj)( `/ M0 r9 w- r* L# I
    {  window.myObj = { };  }
8 V2 u# W2 e( _) e0 h, V    第三种写法& e8 g, r" v' ~" g
    上面这种写法的缺点在于,在某些运行环境中(比如V8、Rhino),window未必是顶层对象。所以,考虑改写成:
" b/ `, `* v4 w2 Y& t5 b; t2 G    if (!this.myObj)  ^3 j% U/ C  _
    {  this.myObj = { };  }- Y0 p2 S" z& \5 ~2 B
    在全局变量的层面中,this关键字总是指向顶层变量,所以就可以独立于不同的运行环境。
: {4 t3 u; N& Z2 C$ T5 V4 s% `/ C    第四种写法
8 s+ J  `" B4 ^5 G- H4 K    但是,上面这样写可读性较差,而且this的指向是可变的,容易出错,所以进一步改写:* j( V  i8 x! w9 b+ F3 g
    var global = this;  if (!global.myObj)
: x- G* F% M2 v6 d+ b    {  global.myObj = { };  }, ?) U) ]. ?/ ^+ o, N9 d# a# \* K
    用自定义变量global表示顶层对象,就清楚多了。
7 ]& _4 I" Z" T; A0 |& @    第五种写法) V6 T5 p* {* x4 Q2 V. B
    还可以使用typeof运算符,判断myObj是否有定义。! |& M3 @6 s' R3 K
    if (typeof myObj == "undefined")
- L2 B% p" [- w" G    {  var myObj = { };  }
* o2 |0 t0 l# t4 N% p% z8 ~, t    这是目前使用最广泛的判断javascript对象是否存在的方法。
+ v( b" D* v" G( ^( u9 M5 c& G    第六种写法
1 i) k4 Y; s% |    由于在已定义、但未赋值的情况下,myObj的值直接等于undefined,所以上面的写法可以简化:
6 G$ H! B& G9 F4 A0 D& n9 w    if (myObj == undefined)  O" J/ i5 T, n2 U% X7 L) k9 c
    {  var myObj = { };  }
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:44:45 | 显示全部楼层

JAVA认证:如何判断JavaScript对象是否存在

这里有两个地方需要注意,首先第二行的var关键字不能少,否则会出现ReferenceError错误,其次undefined不能加单引号或双引号,因为这里比较的是undefined这种数据类型,而不是"undefined"这个字符串。
5 @( g# a3 o/ A( }0 E. x% @* \! u    第七种写法
$ h* {9 l* G9 N! z2 w1 w! C' A+ T. x    上面的写法在"精确比较"(===)的情况下,依然成立:
/ A# H! g8 `( C1 ~  Q+ O    if (myObj === undefined)
4 s+ n& R$ Y, N5 c5 A% Q  V    {  var myObj = { };  }
4 R/ W: X. S, C1 e2 \5 O    第八种写法
% h* o* h! H9 H$ C; g7 R# k6 H    根据javascript的语言设计,undefined == null,所以比较myObj是否等于null,也能得到正确结果:
& W# a2 O5 a1 u6 S8 N% T    if (myObj == null)
% [5 y  a2 ?9 d% o7 _- {3 }+ Y    {  var myObj = { };  }- l% G2 {9 \6 u+ q
    不过,虽然运行结果正确,但是从语义上看,这种判断方法是错的,应该避免。因为null指的是已经赋值为null的空对象,即这个对象实际上是有值的,而undefined指的是不存在或没有赋值的对象。因此,这里只能使用"比较运算符"(==),如果这里使用"精确比较运算符"(===),就会出错。% x8 [$ s" M2 t  c& O
    第九种写法
6 Z4 L; C; j/ W    还可以使用in运算符,判断myObj是否为顶层对象的一个属性:
$ h# j9 n) ?1 S5 f6 `& ?    if (!('myObj' in window))
/ g- |. i6 \) `    {  window.myObj = { };  }
  L8 d3 Z% b3 ?8 M    第十种写法  最后,使用hasOwnProperty方法,判断myObj是否为顶层对象的一个属性:
: x* B" e( Q' L    if (!this.hasOwnProperty('myObj'))
$ y7 n. d, W; R% W  m# |    {  this.myObj = { };  }% P: V; l4 K8 V6 k6 J" R4 {' ]
    总结  1. 如果只判断对象是否存在,推荐使用第五种写法。
. u2 [: m  x3 A4 \, e' j8 w    2. 如果除了对象是否存在,还要判断对象是否有null值,推荐使用第一种写法。
9 [( U3 C3 X/ i. B- v, r3 u- Y* g8 c    3. 除非特殊情况,所有变量都应该使用var命令声明。
5 j6 I3 a) p( q, B0 }# I/ }    4. 为了跨平台,建议避免使用window表示顶层对象。
$ J% g9 T4 @' m0 ^/ U    5. 在Javascript语言中,null和undefined容易产生混淆。在可能同时涉及两者的情况下,建议使用"精确比较"运算符(===)。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-7 14:05 , Processed in 0.261132 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表