前言:本文的对象是javascript新手,如果您不知道document.clear()干什么用的,那么也可以读写去。

关键字:document.clear, dom 0 event model, scope chain

晚上学习"javascript:the definitive guide"的过程中,碰到一件当时看来很“诡异”的事情。为了验证select控件可以通过select.options.length=0;来清空, 我写了一个clear方法。然后使用inline property的形式给一个按钮的click事件赋值:onclick="clear();"。问题就来了,无论我在哪个浏览器上测试,select就 是一点反应没有。我有点奇怪:这么权威的书也出错!(不好意冤枉了作者)

接着我试了一下select.innerHTML="";心想只能用这个方法替代清空了,发现也没有反应。 又试了一下alert,终于发现问题根源了:代码没错,方法的调用有问题。当时我甚至有了“clear是关键字”的猜测(大家不要笑话我)。之后将方法名修改为clearOptions,问题解决了。

问题是解决了,但是还是不大明白为什么clear有问题(终于发现clear不是关键字了)。于是google了一下,发现已经有前辈经历过了。发现clear是document的一个方法,定义与w3c dom 1不过 已经弃之不用了。虽然不用了但还是存在的。由于在dom 0 model中event handler是作为target的属性存在的,因此从代码对应的文档结构可以看出,该按钮的click event handler(本身是一个函数)执行的时候首先要查找clear()方法。Click event handler的scope chain可以简化为:Call Object->input->form->body->document->window。而我们想要调用的clear方法是定义在window下面的(window的属性),在这中间偏偏有一个拦路虎就是document,它也有一个clear方法。这就直接造成了我对definitive guide的作者的误解。

这个原因也找到了,以后写代码的时候要注意了。另外,你会发现这个click event handler要调用一次clear方法很不容易,要经过多少收费站啊!这对于一个关心代码质量的人来说是不可忍受的。比较好的做法是将clear方法直接赋值给click event handler:select.onclick=clear;也可以通过事件注册方法(addEventListener and attachEvent)。代码如下:

Code

这样做也可以解决问题,并且是更好的方法。并且将event handler中用到的方法拷贝到target中作为属性可以避免其它的你不知道的拦路虎,值得推荐。

之后我又试了一下将方法赋值给按钮的onclick属性(参加代码中的btnClear2),原以为这样写也是不能成功的。结果发现不然。经过仔细阅读definitive guide,发现了一个被我忽视的问题:scope of event handler在赋值给html attribute 和html property的时候是不一样的。前者(参考btnClear)的scope chain和之前分析的类似,是比较复杂的,包含了dom tree。但是这一条本身没有标准,因此各个浏览器在实现的时候也可能不一致。后者(参考btnClear2)的scope chain则是正常的,大致是:Call Object->window。因此btnClear2的onclick是没有问题的。



 

posted on 2008-11-04 00:33  zbinxp  阅读(1334)  评论(5)    收藏  举报