阿当的博客











{十二月 14, 2009}   javascript的分层概念

在webrebuild北京站上做的一次分享,总结了一下javascript的分层概念。

   这里特别推荐一下YUI3给我们带来的分层概念:

1)底层(框架提供):封装DOM和Event相关操作,提供跨浏览器兼容的接口,扩展原生javascript语言本身不提供的但又特实用的接口,例如namespace;

2)抽象类层(框架提供):提供类的抽象层,用于统一框架组件层,自定义组件层和应用层中所有类的格式,例如统一初始化方法,毁灭方法,属性如何定义,监听事件在什么方法里等等等等;

3)通用组件层(框架提供):依赖底层的接口,继承自抽象类的抽象类,提供通用型组件,和项目具体需求没有直接关系,也就是说,不是定制型的组件。

4)自定义组件层(开发工程师提供):根据项目需求,定制型的组件,它依赖底层和通用组件层,继承自抽象类层,是根据具体项目进行的封装,定制型组件。

5)应用层(开发工程师提供):这一层是和页面具体需求相关的,面向应用的。用mvc来划分的话,前面四层全是m,这一层是c。它调用前面四层提供的m,集中精力在应用逻辑上。这一层如果需要自定义类,也需要继承自抽象类层。

ppt见:http://www.adanghome.com/share/javascripthierarchical.ppt



{十一月 22, 2009}   标签内联事件和event对象

event对象在IE和firefox下表现是不同的。在IE下,event是window对象的一个属性,是在全局作用域下的,而在firefox里,event对象是做为事件的参数存在的:

===========================

<input type=”button” id=”btn” value=”click me” />

<script type=”text/javascript”>

document.getElementById(“btn”).onclick = function(){

     alert(arguments.length);

};

</script>

===========================

这代代码在IE下弹出0,而在firefox下弹出1。在firefox下这个参数就是event对象了。

如果在标签内联事件中触发事件会如何呢?

===========================

<input type=”button” id=”btn” value=”click me” onclick = “handler();” />

<script type=”text/javascript”>

function handler(){

     alert(arguments.length);

};

</script>

===========================

在IE和firefox下,这段代码弹出的都是0.也就是说,标签内联事件并没有被替换成

===========================

btn.onclick = handler;
function handler(){
alert(arguments.length);
}

===========================

而是替换成了

===========================

btn.onclick = function(){

     handler();

}
function handler(){
alert(arguments.length);
}

===========================

在标签内联事件中,我们使用arguments[0]可以在firefox下访问到event对象。

===========================

<input type=”button” id=”btn” value=”click me” onclick = “alert(arguments[0].type)” />

===========================

因为不使用标签内联事件的话,我们可以给处理函数传参,从而指定arguments[0]的变量名,通常情况下,我们平时也的确是这么处理的:

===========================

<input type=”button” id=”btn” value=”click me” />

<script type=”text/javascript”>

document.getElementById(“btn”).onclick = function(e){

     e = window.event || e;                     //e兼容IE和firefox,指向event对象

};

</script>

===========================

在标签内联事件中我们没办法指定参数名,是不是就没办法直接写个变量在IE和firefox下兼容地指event对象呢?不是的,可以用“event”这个变量名兼容地指向event对象,注意,只能是“event”,如果是“a”,“b”,“Event”之类的全都不行。可能是因为考虑到标签内联事件中无法指定参数变量名,所以故意留个了“event”这个关键字吧。

===========================

<input type=”button” id=”btn” value=”click me” onclick=”alert(event.type);” />

===========================

这段代码在IE和firefox下都可以正常地弹出“click”。

有趣的是,标签内联事件中我们甚至可以写注释,可以使用字符串:

===========================

//只弹出1

<input type=”button” id=”btn” value=”click me” onclick=”alert(1);//alert(2);alert(3);” />

//弹出1和3

<input type=”button” id=”btn” value=”click me” onclick=”alert(1);/*alert(2);*/alert(3);” />

//弹出“string”

<input type=”button” id=”btn” value=”click me” onclick=”var a=’abc’;alert(typeof a);”/>

===========================

如果我们既用标签内联事件绑定了事件,又用DomNode.onxxxx绑定了事件,又会如何呢?

===========================

<input type=”button” id=”btn” value=”click me” onclick=”alert(123);” />

<script type=”text/javascript”>

document.getElementById(“btn”).onclick = function(){

     alert(456);

};

</script>

===========================

会如何呢?会弹出456,不弹出123。相当于

===========================

<input type=”button” id=”btn” value=”click me” />

<script type=”text/javascript”>

document.getElementById(“btn”).onclick = function(){

     alert(123);

};

document.getElementById(“btn”).onclick = function(){

     alert(456);

};

</script>

===========================

后面的处理函数把前面的处理函数覆盖掉了。如果我们给DomNode是通过attachEvent和addEventListener来绑定事件的呢?

===========================

<input type=”button” id=”btn” value=”click me” onclick=”alert(123);” />

<script type=”text/javascript”>

function handler(){
alert(456);
}
if(document.all){
btn.attachEvent(“onclick”,handler);
} else {
btn.addEventListener(“click”,handler,false);
}

</script>

===========================

很顺利地,先弹出了123,后又弹出了456。



{十一月 22, 2009}   关于prototype

protype是个很有趣的属性,它是“类”所持有的属性。在javascript里原生提供的一些内置类,其本质也是“类”,内置类提供的方法我们也可以通过prototype来覆盖掉,这是件很有趣的事情。例如:

=========================================

var str = str2 = “ab,cd,ef,g”;
var arr = str.split(“,”);
String.prototype.split = function(a){
return “hello,you input: ” + a;
}
String.prototype.length = 200;
var arr2 = str2.split(“,”);
alert(str.length);
alert(arr);
alert(arr2);
Array.prototype.toString = function(){
return “12345″;
}
alert(arr);

=========================================

猜猜看,会依次弹出什么?“10”,“ab,cd,ef,g”,“hello,you input: ,”,“12345”。呵呵,看来属性没办法覆盖,第一个没弹出“200”,但方法可以覆盖,不论是String类的split方法,还是Array类的toString方法,都被我们覆盖掉了。

当然,覆盖内置类提供的方法这种操作绝大部分时候都是不好的,通常情况下,我们更多的是为内置类提供更多的方法,让程序更好用,例如:

==========================================

var arr = ["a","b","c"];
var str = arr.join(“-”);
alert(str);
Array.prototype.join2 = function(a){
return this.join(“^^^”+a+”^^^”);
}
str = arr.join2(“-”);
alert(str);

==========================================

我们给内置类添加一个join2方法,让它在join数组的时候,能做更多我们自定义的事。因为修改的是内置类的原型,所以js中所有的原生数据都直接获得了新的方法,这是种很方便的功能。但这样的方法其实并不推荐,它会对原生内置类的原型造成“污染”,可能会出现奇怪的问题,特别是多人合作的时候,或者引入第三方js库的时候,出现一些奇怪的bug,查都不好查。我们更推荐的方法是定义一个新的类,然后把所有需要扩展的功能放到这个新的类里去,通过这个新的类来完成功能,而不是直接修改原型。如:

===========================================

var arr = ["a","b","c"];
var str = arr.join(“-”);
alert(str);
arrayManager = {
join : function(oarr,ostr){
return oarr.join(“^^^”+ostr+”^^^”);
}
}
str = arrayManager.join(arr,”-”);
alert(str);

===========================================

prototype是什么意思呢?它表示“原型”,简单地说,js中的类是分两级来实现的,一级是“原型级”,它比较底层,另一级是“实例级”,实例级的优先级比原型级高,如果new一个类,调用方法的时候,先优先在实例级去查找有无这个方法,如果没有,才会去原型中找。实例级在分配内存时会为每个实例分配一个,而原型级只会在内存中分配一个,通过传址的形式传给每个类的实例。所以为了节约内存,我们更推荐写类的时候将方法通过prototype的方式写出来,而不要写在function里,例如:

=========================================

//不推荐的写法

function Dog(){

this.name = “WangCai”;

this.call = function(){

alert(”wang wang”);

}

}

//推荐的写法

function Dog(){

this.name = “WangCai”;

}

Dog.prototype = {

call : function(){

alert(“wang wang”);

}

}

=========================================

正因为prototype是通过传址的方式供各实例调用的,所以如果对prototype进行了修改,无需重新再new一遍,实例的方法就已经更改了:

=========================================

function Dog(name){
this.name = name;
}
Dog.prototype.call = function(){
alert(“I’m “+this.name);
}
var myDog = new Dog(“WangCai”);
myDog.call();
Dog.prototype.call = function(){
alert(“wang wang wang wang wang”);
}
myDog.call();

function Cat(name){
this.name = name;
this.call = function(){
alert(“I’m “+this.name);
}
}
var myCat = new Cat(“Mimi”);
myCat.call();
Cat.prototype.call = function(){
alert(“miao miao miao miao miao”);
}
myCat.call();

=========================================

myDog第一次call的时候,弹的是I’m WangCai,第二次就是wang wang wang wang wang了 ;myCat两次都弹的是I’m Mimi。

正是因为prototype的这种特性,所以open api的系统里,因为会支持第三方开发,为了防止第三方恶意覆盖掉javascript内置类的方法,都会封装一套接口给第三方使用,以阻止它们访问原生内置类的原型。



{十一月 19, 2009}   [原创] 如何在ietester下使用firebug

首先,需要说明的是,此firebug并不是firefox下的插件firebug。众所周知,firebug是firefox下的调试利器,但在ie下没有相关的插件,为了在ie下实现firebug功能,所以出了这么一个组件,它是完全用js生成的仿firebug界面。功能当然没有真正的firebug强大,但其操作和firebug很像,界面也像,对于习惯firebug的工程师来说,使用它非常亲切。其官方网站是http://uicss.cn/r.php?hr=http://getfirebug.com/lite.html

    有一点很让人郁闷的是,官方提供的加载它的方法是给html加载一个<script>标签,引用这段js到页面里去。这个在开发阶段当然是没有问题,但如果是调试已经在线上的页面,比如http://www.sina.com.cn,怎么办呢?有办法能像firefox下的firebug一样随时可以调用吗?

     有,一个最简单的办法就是使用油猴。IE下的油猴见:http://www.bhelpuri.net/Trixie/

      如果是使用maxthon的话,maxthon也有自己的油猴插件,叫做more scripts,见:http://addons.maxthon.cn/zh_CN/search/all/bW9yZSBzY3JpcHRz

      但问题是我们经常需要在ie6,ie7,ie8三个不同版本的ie下进行调试,如果是其中一个版本出现了问题呢?当然,ie6,ie7和ie8的js引擎没啥大区别,主要是指css方面的问题。我们如何调试呢?为了调试ie6,ie7和ie8,我们最常用的软件是ietester,而ietester本身其实也带调试工具DebugBar。用DEbugBar比起ie自带的developer toolbar最大的好处是它可以运行在不同的内核之上,ie6,7,8都可以进行调试。但DebugBar真的是超级难用!!如果能将ietester的多ie内核功能,结合firebug的易用性,该多好啊!可是ietester下没有油猴。。。

      还是有办法的,现在就告诉你我的办法。首先打开ietester的DebugBar,切换到脚本标签,可以看到最下面一栏有个输入框,注释写着”// Javascript 控制台”,这是个类似于firebug的脚本控制台的功能,可以输入js并运行。如截图:

我们在这里输入脚本:

=============================================

var s = document.createElement(“script”);
s.src = ‘http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js’;
s.type=”text/javascript”;
if(document.all){
   s.onreadystatechange = function(){
    if(this.readyState == “loaded” || this.readyState == “complete”){
     alert(“loaded success in ie”);
    }
   }
} else {
   s.onload = function(){
    alert(“load success”);
   }
}
document.body.appendChild(s);
================================================

这里的思路是动态创建一个script标签,然后监听它的onload事件,当它加载完成时,会alert一下加载成功信息。运行脚本,等到弹出”loaded success in ie”后,表示我们的firebug组件的脚本已经加载进来了。但此时,firebug的界面并没有出现!别着急,我们将输入框中的代码清除掉,再输入如下代码:

==================

firebug.init();

==================

    运行它,过一会儿,就会看到firebug的界面出现了!我用这个方法成功在htttp://www.sina.com.cn调出了firebug,如截图所示:


 

ok,ietester下我们已经可以使用firebug了。接下来,我们看看不同版本ie内核下的firebug能不能按我们预期的那样,在不同内核下真实显示当前的信息。

写了个小demo,如下:

=======================================

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd“>
<html>
<head>
<title>阿当制作</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
</head>
<body>
<style type=”text/css”>
#test{padding:20px;background:green;*background:blue;_background:yellow}
</style>
<div id=”test”>hello world</div>
</body>
</html>

=======================================
定义了一个id为test的div,用css hack让它在ie6,7,8下背景色分别为yellow,blue,green。然后,看看在不同内核版本下firebug会如何显示当前的样式信息呢?见截图:





{十一月 18, 2009}   动态加载script和css标签的onload问题

在firefox下,动态加载script标签和css标签,是可以简单地监听onload事件的,但在ie下,监听onload事件无效。为了解决这个问题,可以改用监听onreadystatechange,结合判断readyState的值是否等于loaded 或complete来判断是否onload。

YUI根据ie,webkit和其它做了三种情况区分。实际工作中,我们只用考虑ie和ff就差不多了,写了个简单的小demo,动态加载ie下的firebug组件:

=================================================

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>阿当制作</title>
</head>

<body>
<script type=”text/javascript”>
var s = document.createElement(“script”);
s.src = ‘http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js’;
s.type=”text/javascript”;
if(document.all){
s.onreadystatechange = function(){
if(this.readyState == “loaded” || this.readyState == “complete”){
alert(“loaded success in ie”);
}
}
} else {
s.onload = function(){
alert(“load success”);
}
}
document.body.appendChild(s);
</script>
</body>
</html>



{十月 22, 2009}   [原创 js]自定义元素位置和大小

用YUI2做的一个小demo,实现了元素的drag和resize功能,自定义添加或减少元素,还可以将元素的位置,长宽等信息打印出来。

演示地址:www.adanghome.com/js_demo/1/

代码如下:

==========================================================
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> 阿当制作</title>
<link type=”text/css” rel=”stylesheet” href=”http://assets.taobaocdn.com/app/tbs/css/public_1_0_0.css” />
<link type=”text/css” rel=”Stylesheet” href=”http://assets.taobaocdn.com/app/tbs/css/jf_express_1_0_0.css” />
<style type=”text/css”>
#wrapper{width:950px;margin:50px auto;}
#previewBox{float:left;display:inline;border:2px solid #666;width:750px;position:relative;height:420px;}
/*#previewBox .leftApp{filter:alpha(opacity=70); opacity: .7;}*/
#inputsWrapper{float:right;display:inline;width:140px;padding:10px;border:2px solid #e0e0de}
#inputsBox span,.leftApp{display:block;margin-top:5px;background:#f2f9ff;border:2px solid #98d6fd;height:22px;line-height:22px;text-align:center;color:#000;cursor:move;font-size:14px;}
p.leftApp,span.leftApp,div.leftApp{position:absolute;margin:0;width:136px;left:0;top:0}
.leftApp_closeBtn{position:absolute;right:15px;top:5px;cursor:pointer;}
#infoBox{padding:10px;margin-top:10px;border:3px solid #ccc;}
</style>
</head>
<body>
<div id=”wrapper”>
<div id=”previewBox”><p style=”width:200px;height:100px;left:50px;top:30px;” myname=”a”>发件人姓名</p><p myname=”b”>发件人地址</p></div>
<div id=”inputsWrapper”>
<h2>打印项 <img src=”http://assets.taobaocdn.com/app/tbs/img/jf_tip.gif” title=”拖动您需要打印的内容项放置到左侧模板中适合的位置。” /></h2>
<p id=”inputsBox”>
<span myname=”a”>发件人姓名</span>
<span myname=”b”>发件人电话</span>
<span myname=”c”>发件人公司</span>
<span myname=”d”>发件人地址</span>
<span myname=”e”>发件人邮编</span>
<span myname=”f”>收件人姓名</span>
<span myname=”g”>收件人电话</span>
<span myname=”h”>收件人地址</span>
<span myname=”i”>收件人邮编</span>
<span myname=”j”>货物清单</span>
<span myname=”k”>发货单号</span>
<span myname=”l”>自定义项</span>
</p>
</div>
<p><input type=”button” value=”显示模块信息” id=”btn” /><p>
<p id=”infoBox”></p>
</div>
<script type=”text/javascript” src=”http://assets.taobaocdn.com/yui/2.7.0/build/yuiloader/yuiloader-min.js”></script>
<script type=”text/javascript”>
var loader = new YAHOO.util.YUILoader({base:”http://assets.taobaocdn.com/yui/2.7.0/build/”});
loader.require(['dom', 'event', 'dragdrop','resize','animation']);
function init(){
var Y=YAHOO.lang,YE = YAHOO.util.Event,YD = YAHOO.util.Dom,YDC=YD.getElementsByClassName,YUC = YAHOO.util.Connect,JSON = YAHOO.lang.JSON,YR = YAHOO.util.Resize;
var CONFIG = {
leftAppContainer : “previewBox”,
rightAppContainer : “inputsBox”,
leftApp : “leftApp”
};

YAHOO.namespace(“express”);

//====================
// LeftApp类
//====================
YAHOO.express.LeftApp = function(id, config) {
this.manager = YD.get(config.manager);
this.el = YD.get(id);
this.el.mytext = this.el.innerHTML;
YAHOO.express.LeftApp.superclass.constructor.call(this, id, config);
YE.on(this.el,”click”,function(){
this.manager.maxAdd();
YD.setStyle(this.el,”zIndex”,this.manager.max);
},null,this);
this.Init();
};

YAHOO.extend(YAHOO.express.LeftApp, YR, {
Init : function(){
this.addCloseBtn();
},
addCloseBtn : function(){
var closeBtn = document.createElement(“img”);
closeBtn.src = “http://assets.taobaocdn.com/app/tbs/img/btn_del.gif”;
closeBtn.className=”leftApp_closeBtn”;
this.el.appendChild(closeBtn);
YE.on(closeBtn,”click”,function(){
this.el.parentNode.removeChild(this.el);
},null,this);
}
});

//=====================
//    LeftApp管理对象
//=====================
YAHOO.express.LeftAppManager = {
max:10,
init : function(){
var leftAppEls = YDC(“leftApp”,”*”,”previewBox”);
for(var i=0,n=leftAppEls.length;i<n;i++){
this.addMod(leftAppEls[i]);
}
},
addMod : function(el){
new YAHOO.express.LeftApp(el,{
handles: ‘all’,
knobHandles: true,
hover:true,
proxy: true,
draggable: true,
manager:this
});
},
maxAdd : function(){
this.max++;
},
getAppsInfo : function(imgInfo){
var leftAppEls = YDC(“leftApp”,”*”,”previewBox”) , wid = 750 , hei = 420 , info = [] , node;
for(var i=0,n=leftAppEls.length;i<n;i++){
node = leftAppEls[i];
info.push(‘{“width”:”‘+ Math.round((node.offsetWidth – 4)*100/wid) + ‘%”,”height”:”‘ + Math.round((node.offsetHeight – 4)*100/hei) + ‘%”,”left”:”‘ + (/%$/.test(YD.getStyle(node,”left”)) ? YD.getStyle(node,”left”) : Math.round(parseInt(YD.getStyle(node,”left”),10)*100/wid) + ‘%’) + ‘”,”top”:”‘ + (/%$/.test(YD.getStyle(node,”top”)) ? YD.getStyle(node,”top”) : Math.round(parseInt(YD.getStyle(node,”top”),10)*100/hei) + ‘%’) + ‘”,”name”:”‘+ (node.myname ? node.myname : node.getAttribute(“myname”))+’”,”text”:”‘+(node.mytext ? node.mytext : node.getAttribute(“mytext”))+’”}’);
}
info = info.join(“,”);
info = “[" + info + "]“;
return info;
}
}

//====================
// RightApp类
//====================
YAHOO.express.RightApp = function(id, sGroup, config) {
YAHOO.express.RightApp.superclass.constructor.call(this, id, sGroup, config);
var el = this.getDragEl();
YD.setStyle(el, “opacity”, 0.67);
};

YAHOO.extend(YAHOO.express.RightApp, YAHOO.util.DDProxy, {
startDrag: function(x, y) {
var dragEl = this.getDragEl();
var clickEl = this.getEl();
YD.setStyle(clickEl, “visibility”, “hidden”);
dragEl.innerHTML = clickEl.innerHTML;
YD.setStyle(dragEl, “color”, YD.getStyle(clickEl, “color”));
YD.setStyle(dragEl, “backgroundColor”, YD.getStyle(clickEl, “backgroundColor”));
YD.setStyle(dragEl, “fontSize”, YD.getStyle(clickEl, “fontSize”));
YD.setStyle(dragEl, “lineHeight”, YD.getStyle(clickEl, “lineHeight”));
YD.setStyle(dragEl, “textAlign”, YD.getStyle(clickEl, “textAlign”));
YD.setStyle(dragEl, “border”, “2px solid #98D6FD”);
},
endDrag: function(e) {
var srcEl = this.getEl();
var proxy = this.getDragEl();
YD.setStyle(proxy, “visibility”, “”);
if(YD.getRegion(CONFIG.leftAppContainer).contains(YD.getRegion(proxy))){
var newNode = document.createElement(“p”);
newNode.innerHTML = srcEl.innerHTML;
newNode.myname = srcEl.getAttribute(“myname”);
YD.get(CONFIG.leftAppContainer).appendChild(newNode);
YD.addClass(newNode,CONFIG.leftApp);
YD.setXY(newNode,YD.getXY(proxy));
YAHOO.express.LeftAppManager.addMod(newNode);
YD.setStyle(proxy, “visibility”, “hidden”);
YD.setStyle(srcEl, “visibility”, “”);
} else {
var a = new YAHOO.util.Motion(
proxy, {
points: {
to: YD.getXY(srcEl)
}
},
0.2,
YAHOO.util.Easing.easeOut
)
a.onComplete.subscribe(function() {
YD.setStyle(proxy, “visibility”, “hidden”);
YD.setStyle(srcEl, “visibility”, “”);
});
a.animate();
}
}
});

//=====================
//    RightApp管理对象
//=====================
YAHOO.express.RightAppManager = {
init : function(){
var rightAppEls = YD.get(CONFIG.rightAppContainer).getElementsByTagName(“span”);
for(var i=0,n=rightAppEls.length;i<n;i++){
new YAHOO.express.RightApp(rightAppEls[i],”right”);
}
}
}

//==================
//    程序初始化
//==================
function init(){
YAHOO.express.LeftAppManager.init();
YAHOO.express.RightAppManager.init();
YE.on(“btn”,”click”,function(){
YD.get(“infoBox”).innerHTML = YAHOO.express.LeftAppManager.getAppsInfo();
});
};
init();
}
</script>
<script type=”text/javascript”>
if(typeof init == “function”){
loader.onSuccess = init;
}
loader.insert();
</script>
</body>
</html>



{十月 22, 2009}   验证中英文,数字和下划线中划线

    遇到个正则的问题,要求验证中英文,数字和下划线中划线可以通过,其它字符不能通过。

     英文和数字好说,\w,下划线和中划线也好说,-_,然后是中文判断,\u0391-\uFFE5。于是我写了这个正则:

    if(/[^\w_-\u0391-\uFFE5]/.test(str)),结果发现英文数字下划线和中划线都可以通过,唯独中文不能通过!很奇怪。

    换了下顺序,将中文的判断放在了前面,如下if(/[^\u0391-\uFFE5\w_-]/.test(str)就正常了。奇怪了。



{十月 13, 2009}   写的某个网站的脚本
记录一下,一些习惯用法已经不想改变了,直接拿出来copy,所以mark一下。

脚本地址:http://assets.taobaocdn.com/app/tbs/js/manage_1_0_7.js



{十月 10, 2009}   formEl.submit is not a function的原因

   今天遇到点小意外,在调用一个form节点的submit方法时,提示submit is not a function,检查了半天,实在想不出来是什么原因,最后我想,既然它不是function,那么好吧,你告诉我它是什么吧,把submit打印出来了,说是inputHTMLElement。。。

    原来是因为给submit按钮取了“submit”这个name,formEl.submit没有指向formEl的submit方法,而是指向了自己的表单项。。。汗,不要给你的表单项乱取名啊,搞不好就覆盖form节点的方法或属性了。。。



{九月 30, 2009}   js中用于继承的函数extend——摘自《javascript设计模式》

这个方法摘自《javascript设计模式》,因为作者对YUI非常熟悉,所以方法的的思路和YUI一样。方法如下:

function extend(subClass,superClass){

    var F = function(){};

     F.prototype = superClass.prototype;

     subClass.prototype = new F();

     subClass.prototype.constructor = subClass;

      subClass.superclass = superClass.prototype;

      if(superClass.prototype.constructor == Object.prototype.constructor){

         superClass.prototype.constructor = superClass;

      }

}




about

打造高品质的前端代码

pages
categories
archive
et cetera