由clear方法想到的

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

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

晚上学习"javascript:the definitive guide"的过程中,碰到一件当时看来很“诡异”的事情。为了验证select控件可以通过select.options.length=0;来清空, 我写了一个clear方法。然后使用inline property的形式给一个按钮的click事件赋值:οnclick="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.οnclick=clear;也可以通过事件注册方法(addEventListener and attachEvent)。代码如下:ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SelectDemo.aspx.cs" Inherits="SelectDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>select demo</title>
ExpandedBlockStart.gifContractedBlock.gif    
<script type="text/javascript">
ExpandedSubBlockStart.gifContractedSubBlock.gif    
function addOption(text,value){
        
var select=document.getElementsByTagName("select")[0];
        
var op=new Option(text,value,false,false);
        
var l=select.options.length;
        select.options[l]
=op;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
function deleteOption(i){
        
var select=document.getElementsByTagName("select")[0];
        select.options[i]
=null;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
function clear(){
        
var select=document.getElementsByTagName("select")[0];
        select.options.length
=0;
        alert(
typeof(this.addOption));
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
var $=function(id){return typeof(id)=="string"?document.getElementById(id):id;}
ExpandedSubBlockStart.gifContractedSubBlock.gif    
function pageLoad(){
        
var btn=$('btnClear');
//        if(document.addEventListener)
//
            btn.addEventListener("click",clear,false);
//
        else if(document.attachEvent){
//
            btn.attachEvent("onclick",clear);
//
        }
        btn.onclick=clear;
    }

    
</script>
</head>
<body onload="pageLoad()">
    
<form id="form1" runat="server">
    
<div>
    
<select id="list1">
        
<option value="1">Apple</option>
        
<option value="2">Google</option>
        
<option value="3">Microsoft</option>
    
</select>
    
<input type="button" value="add" onclick="addOption('Sun',4);" />
    
<input type="button" value="delete" onclick="deleteOption(0);" />
    
<input id="btnClear" type="button" value="clear" />
    
</div>
    
</form>
</body>
</html

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SelectDemo.aspx.cs" Inherits="SelectDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>select demo</title>
    
<script type="text/javascript">
    
function addOption(text,value){
        
var select=document.getElementsByTagName("select")[0];
        
var op=new Option(text,value,false,false);
        
var l=select.options.length;
        select.options[l]
=op;
    }
    
function deleteOption(i){
        
var select=document.getElementsByTagName("select")[0];
        select.options[i]
=null;
    }
    
function clear(){
        
var select=document.getElementsByTagName("select")[0];
        select.options.length
=0;
        alert(
typeof(this.addOption));
    }
    
var $=function(id){return typeof(id)=="string"?document.getElementById(id):id;}
    
function pageLoad(){
        
var btnClear=$('btnClear'),btnAdd=$('btnAdd'),btnDelete=$('btnDelete');
        
var btnClear1=$('btnClear1'), btnClear2=$('btnClear2');
        btnClear1.onclick
=clear;
        btnClear2.onclick
=function(){clear();}
        btnAdd.onclick
=function(){addOption('Sun',4);};
        btnDelete.onclick
=function(){deleteOption(0);};
    }
    
</script>
</head>
<body onload="pageLoad()">
    
<form id="form1" runat="server">
    
<div>
    
<select id="list1" name="select1">
        
<option value="1">Apple</option>
        
<option value="2">Google</option>
        
<option value="3">Microsoft</option>
    
</select>
    
<input id="btnAdd" type="button" value="add" />
    
<input id="btnDelete" type="button" value="delete" />
    
<input id="btnClear" type="button" value="clear" onclick="clear();" />
    
<input id="btnClear1" type="button" value="clear1" />
    
<input id="btnClear2" type="button" value="clear2" />
    
</div>
    
</form>
</body>
</html>

ContractedBlock.gif ExpandedBlockStart.gif Code
ExpandedBlockStart.gifContractedBlock.gif<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SelectDemo.aspx.cs" Inherits="SelectDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>select demo</title>
ExpandedBlockStart.gifContractedBlock.gif    
<script type="text/javascript">
ExpandedSubBlockStart.gifContractedSubBlock.gif    
function addOption(text,value){
        
var select=document.getElementsByTagName("select")[0];
        
var op=new Option(text,value,false,false);
        
var l=select.options.length;
        select.options[l]
=op;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
function deleteOption(i){
        
var select=document.getElementsByTagName("select")[0];
        select.options[i]
=null;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
function clear(){
        
var select=document.getElementsByTagName("select")[0];
        select.options.length
=0;
        alert(
typeof(this.addOption));
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
var $=function(id){return typeof(id)=="string"?document.getElementById(id):id;}
ExpandedSubBlockStart.gifContractedSubBlock.gif    
function pageLoad(){
        
var btnClear=$('btnClear'),btnAdd=$('btnAdd'),btnDelete=$('btnDelete');
        
var btnClear1=$('btnClear1'), btnClear2=$('btnClear2');
        btnClear1.onclick
=clear;
ExpandedSubBlockStart.gifContractedSubBlock.gif        btnClear2.onclick
=function(){clear();}
ExpandedSubBlockStart.gifContractedSubBlock.gif        btnAdd.onclick
=function(){addOption('Sun',4);};
ExpandedSubBlockStart.gifContractedSubBlock.gif        btnDelete.onclick
=function(){deleteOption(0);};
    }

    
</script>
</head>
<body onload="pageLoad()">
    
<form id="form1" runat="server">
    
<div>
    
<select id="list1" name="select1">
        
<option value="1">Apple</option>
        
<option value="2">Google</option>
        
<option value="3">Microsoft</option>
    
</select>
    
<input id="btnAdd" type="button" value="add" />
    
<input id="btnDelete" type="button" value="delete" />
    
<input id="btnClear" type="button" value="clear" onclick="clear();" />
    
<input id="btnClear1" type="button" value="clear1" />
    
<input id="btnClear2" type="button" value="clear2" />
    
</div>
    
</form>
</body>
</html>

这样做也可以解决问题,并且是更好的方法。并且将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是没有问题的。



 

转载于:https://www.cnblogs.com/zbinxp/archive/2008/11/04/1325935.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值