本帖最后由 群发软件 于 2017-5-31 00:38 编辑
如果是从内部架构与理念划分,目前JavaScript框架可以划分为5类。
第1种
出现的是以命名空间为导向的类库或框架,如创建一个数组用new Array(),生成一个对象用new Object(),完全的Java风格,因此我们就可以以某一对象为根,不断为它添加对象属性或二级对象属性来组织代码,金字塔般地垒叠起来。代表作如早期的YUI与EXT。
第2种
出现的是以类工厂为导向的框架,如著名的Prototype,还有mootools、Base2、Ten。它们基本上除了最基本的命名空间,其他模块都是一个由类工厂衍生出来的类对象。尤其是mootools 1.3,把所有类型都封装成Type类型。
第3种
就是以jQuery为代表的以选择器为导向的框架,整个框架或库主体是一个特殊类数组对象,方便集化操作——因为选择器通常是一下子选择到N个元素节点,于是便一并处理了。jQuery包含了几样了不起的东西:“无new实例化”技术,$(expr)就是返回一个实例,不需要显式地new出来;get first set all访问规则:数据缓存系统。这样就可以复制节点的事件了。此外,IIFE(Immediately-Invoked Function Expression)也被发掘出来。
第4种
就是以加载器串联起来的框架,它们都有复数个JavaScript文件,每个JavaScript文件都以固定规则编写。其中最著名的莫过于AMD。模块化是JavaScript走向工业化的标志。《Unix编程艺术》列举的众多“金科玉律”的第一条就是模块,里面有言——“要编写复杂软件又不至于一败涂地的唯一方法,就是用定义清晰的接口把若干简单模块组合起来,如此一来,多数问题只会出现在局部,那么还有希望对局部进行改进或优化,而又不至于牵动全身”。许多企业内部框架都基本采取这种架构,如Dojo、YUI、kissy、qwrap和mass等。
第5种
就是具有明确分层架构的MV*框架。首先是JavaScript MVC(现在叫CanJS)、backbonejs、spinejs,然后更符合前端实际的MVVM框架,如knockout、ember、angular、avalon、winjs。在MVVM框架中,原有DOM操作被声明式绑定取代了,由框架自行处理,用户只需专注于业务代码。
下面是有关框架特征的结论。
对基本数据类型的操作是基础,如jQuery就提供了trim、camelCase、each、map等方法,对Prototype.js等侵入式框架则是在原型上添加camelize等方法。
类型的判定必不可少,常见形式是isXXX系列。
选择器、domReady、Ajax是现代框架的标配。
DOM操作是重中之重,节点的遍历、样式的操作、属性操作也属于它的范畴,是否细分就看框架的规模了。
brower sniff已过时,feature detect正被应用。不过特性侦测还是有局限性,如果针对于某个浏览器版本的渲染Bug、安全策略或某些Bug的修正,还是要用到浏览器嗅探。但它应该独立成一个模块或插件,移除框架的核心。
现在主流的事件系统都支持事件代理。
数据的缓存与处理,目前浏览器也提供data-*属性进行这方面的工作,但不太好用,需要框架的进一步封装。
动画引擎,除非你的框架像Prototype.js那样拥有像script.aculo.us这样顶级的动画框架做后盾,最好也加上。
插件的易开发和扩展性。
提供诸如Deferred这样处理异步的解决方案。
即使不专门提供一个类工厂,也应该存在一个名为extend或mixin的方法对对象进行扩展。jQuery虽然没有类工厂,但在jQuery UI中也不得不增加一个,可见其重要性。
自从jQuery出来一个名为noConflict的方法,新兴的框架都带此方法,以求狭缝中生存。
许多框架非常重视Cookie操作。
<!doctype html><html><head><title>分类选择器</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style>
.box{margin-top:300px;margin-
left:300px;}#btn{width:50px;height:25px;float:left}#classifyTree{float:left;position:relative;display:none;}#classifyTree ul{position:absolute;left:100%;top:0;border:1px solid #333;margin:0;padding:0
;display:none}#classifyTree li{float:left;list-style-
type:none;position:relative;}#classifyTree li:hover{background:#999
}#classifyTree span{float:left;display:block;height:20px;white-
space:nowrap}</style></head><body><div class="box" id="box"> <input type="button" id="btn" value=""/> <div id="classifyTree">
<!-- html结构将会如下 <ul> <li> <span>衣服</span> <ul> <li><span title="1">衬衣</span></li> <li><span title="2">毛衣</span></li> <li><span title="3">内衣</span></li> </ul> </li> <li> <span>裤子</span> <ul> <li><span>内裤</span></li> <li><span>长裤</span></li> <li><span>短裤</span></li> </ul> </li> <li> <span>鞋子</span> <ul> <li><span>皮鞋</span></li> <li><span>布鞋</span></li> <li><span>草鞋</span></li> </ul> </li> </ul>--> </div></div></body><script type="text/javascript">
//pid代表父ID,0代表根 var json =
[ {"name":"衣服" , "id" : "1" , "pid" : 0
}, {"name":"裤子" , "id" : "2" , "pid" : 0
}, {"name":"鞋子" , "id" : "3" , "pid" : 0
}, {"name":"衬衣" , "id" : "4" , "pid" : 1
}, {"name":"毛衣" , "id" : "5" , "pid" : 1
}, {"name":"内衣" , "id" : "6" , "pid" : 1
}, {"name":"大" , "id" : "10" , "pid" : 6
}, {"name":"大" , "id" : "11" , "pid" : 7
}, {"name":"大" , "id" : "7" , "pid" : 4
}, {"name":"中" , "id" : "8" , "pid" : 4
}, {"name":"小" , "id" : "9" , "pid" : 4
} ];//IE下 最后一个数组不能给逗号,否则会多算一条 var classifySelect =
{ treeRoot : document.getElementById("classifyTree"),
//dom树根 btn : document.getElementById("btn"
), json : this.json, rootId : 0,
//一级分类ID //根据json建立dom树 setDomTree :
function(){ function creatEl(name){
return document.createElement(name);}
//创建标签 var ul = creatEl("ul"
); //先建立根节点 for(
var i=0;i<
this.json.length;i++
){ if(
this.json
.pid==this.rootId){ var li = creatEl("li"); var span = creatEl("span"); span.title = this.json.id; span.innerHTML = this.json.name; li.appendChild(span); ul.appendChild(li); this.json.splice(i,1);//已经载入页面删除当前数组 i--;//数组删除,下次循环继续查询当前位置 } } this.treeRoot.appendChild(ul); this.addNodes(this.treeRoot.getElementsByTagName("ul")[0]);//获取插入的根ul,再查询是否有子类 }, //查询是否还有子分类,有则添加 addNodes : function(pUl){//parent ul function creatEl(name){return document.createElement(name);}//创建标签 var li = pUl.getElementsByTagName("li"); /* 遍历li。特别注意:由于下个for循环条件满足添加了子类后,pUl(也就是根ul)中便添加了li,li.length会改变。 新添加的li永远在当前指针节点之后,所以不会冲突或者遗漏,而且能够在此循环结束后完成整个dom树 */ for(var i=0;i<li.length;i++){ var pid = parseInt(li.getElementsByTagName("span")[0].title);//根据span的title存储的ID,查找json队列里是否还有子类//alert(typeof(pid)); var ul = creatEl("ul"); var isExist = false;//是否存在子类 for(var j=0;j<this.json.length;j++){//遍历json, if(this.json[j].pid == pid){//pid相同,添加节点到pUl var newLi = creatEl("li"); var newSpan = creatEl("span"); newSpan.title = this.json[j].id; newSpan.innerHTML = this.json[j].name; newLi.appendChild(newSpan); ul.appendChild(newLi); this.json.splice(j,1); j--; isExist = true; } } if(isExist){ li.appendChild(ul); } } }, //查找分类 seekClassify : function(){ var self = this; //点击触发分类显示 this.btn.onclick = function(){ self.treeRoot.style.display = "block"; self.nextClassify(self.treeRoot,"block");//显示根分类 } }, //绑定事件,隐藏和显示下级分类 bindHover : function(){ var self = this; var li = self.treeRoot.getElementsByTagName("li");//获取所有li //绑定根 var root =self.treeRoot.getElementsByTagName("ul")[0]; root.onmouseover= function(){ self.nextClassify(self.treeRoot,"block"); } root.onmouseout = function(){ self.nextClassify(self.treeRoot,"none"); } for(var i=0;i<li.length;i++){ li.onmouseover = function(){ if(self.isNextClassify(this)){ self.nextClassify(this,"block"); } } li.onmouseout = function(){ if(self.isNextClassify(this)){ self.nextClassify(this,"none"); } } } }, //显示或者隐藏下级分类 nextClassify : function(self,status){ var ul = self.getElementsByTagName("ul")[0]; ul.style.display = status; }, //检查是否有下级分类,如果没有可以选择 isNextClassify : function(li){ var self = this; if(li.getElementsByTagName("ul")[0]){ return true; }else{ li.getElementsByTagName("span")[0].onclick = function(){//绑定选择事件 self.btn.value = this.title; self.nextClassify(self.treeRoot,"none");//选择完毕隐藏 } return false; } }, init : function(){ this.setDomTree(); this.seekClassify(); this.bindHover(); } } classifySelect.init();</script></html>
1、赋值语句:var
2.return语句
3、条件分支语句 if...else,switch
4、循环语句 for,for...in,while,break,continue.
5、对象操作语句with,new,delete,this
6、注释语句
7、函数定义语句:function,return
1、变量声明赋值语句:var
var语句声明了一个变量的名称,同时也可以让这个变量具有一个初始值。
如果var语句在一个函数中声明变量,则这个变量的有效区域只限于这个函数,叫局部变量;如果var语句在函数体外,则有效区为整个应用程序,叫全局变量。
在函函数体外声明一个变量可以不用var,给出变量的值就可以了。(但推荐使用var)
var的语法如下:
例:
var Computer=9 //Computer 是一个整数变量,初值为9
Computer=9 //Computer 是一个整数变量,初值为9 |
2.return语句
return语句指明将由函数返回的值。
语法如下:
return 表达式;
如果这里省略了表达式,或者函数结束时根本没有return语句,这个函数就返回一个undefined类型的值。
3、条件分支语句 if...else,switch
1.if...else
1)基本格式
if(表述式)
语句段1;
......
else
语句段2;
......
2)功能:若表达式为true,则执行语句段1;否则执行语句段2。
3)说明:
·if -else 语句是JavaScript中最基本的控制语句,通过它可以改变语句的执行顺序。
·表达式中必须使用关系语句,来实现判断,它是作为一个布尔值来估算的。
·它将零和非零的数分别转化成false和true。
·若if后的语句有多行,则必须使用花括号将其括起来。
4)if语句的嵌套
if(布尔值)语句1;
else(布尔值)语句2;
else if(布尔值)语句3;
……
else 语句4;
在这种情况下,每一级的布尔表述式都会被计算,若为真,则执行其相应的语句,否则执行else后的语句。
示例:
<script>
function abcd()
{
var d=confirm("请选择确定或者取消");
if (d==1){
alert("你选择的是确定");
}
else{
alert("你选择的是取消");
}
}
</script> |
5).switch语句
分支语句switch可以根据一个变量的不同取值而采取不同的处理方法。
switch的语法如下:
switch(表达式){
case label 1:
执行语句;
case label 2:
执行语句;
……
default :
执行语句;
}
示例:
<script>
var d= new Date();
switch(d.getDate()){
case 0 : document.write("星期一");break;
case 1 : document.write("星期二");break;
case 2 : document.write("星期三");break;
case 3 : document.write("星期四");break;
case 4 : document.write("星期五");break;
case 5 : document.write("星期六");break;
case 6 : document.write("星期日");break;
}
</script> |
4、循环语句 for,for...in,while,break,continue.
1.for
1)基本格式
for(初始化;条件;增量)
语句集;
2)功能:实现条件循环,当条件成立时,执行语句集,否则跳出循环体。
3)说明:
·初始化参数告诉循环的开始位置,必须赋予变量的初值;
·条件:是用于判别循环停止时的条件。若条件满足,则执行循环体,否则 跳出。
·增量:主要定义循环控制变量在每次循环时按什么方式变化。
·三个主要语句之间,必须使用逗号分隔。
2.for...in
这个语句与for语句有一点不同。它循环的范围是一个对象所有的属性或者是一个数组的所有元素。
语法如下:
for(变量in对象或数组) {
执行语句......
}
4).while语句
1)基本格式
while(条件)
语句集;
该语句与For语句一样,当条件为真时,重复循环,否则退出循环。
2)For与while语句
两种语句都是循环语句,使用For语句在处理有关数字时更易看懂,也较紧凑;而while循环对复杂的语句效果更特别。
示例:
这是1级标题
这是2级标题
这是3级标题
<script>
i=1;
while (i<=3){
document.write("<h"+i+">这是"+i+"级标题"+"</h"+i+">");
i++;
}
</script> |
4、break和continue语句
与C++语言相同,使用break语句使得循环从For或while中跳出,continue使得跳过循环内剩余的语句而进入下一次循环。
5、对象操作语句with,new,delete,this
1).with
使用该语句的意思是:在该语句体内,任何对变量的引用被认为是这个对象的属性,以节省一些代码。
with object{
...}
所有在with语句后的花括号中的语句,都是在后面object对象的作用域的。
2).this关键字
this是对当前的引用,在JavaScript由于对象的引用是多层次,多方位的,往往一个对象的引用又需要对另一个对象的引用,而另一个对象有可能又要引用另一个对象,这样有可能造成混乱,最后自己已不知道现在引用的那一个对象,为此JavaScript提供了一个用于将对象指定当前对象的语句this。
3).New运算符
虽然在JavaScript中对象的功能已经是非常强大的了。但更强大的是设计人员可以按照需求来创建自己的对象,以满足某一特定的要求。使用New运算符可以创建一个新的对象。其创建对象使用如下格式:
Newobject=NEW Object(Parameters table);
其中Newobject创建的新对象:object是已经存在的对象; parameters table参数表;new是JavaScript中的命令语句。
如创建一个日期新对象
newData=New Data()
birthday=New Data (December 12.1998)
之后就可使NewData、birthday作为一个新的日期对象了。
4.delete
同new相反,可以删除一个对象的实例。
6、注释语句(只是给人看的,浏览器不执行的语句)
// 这是一个单行的注释
/* 这样的注释可以是多行的
......
*/
7、函数定义语句:function,return
1.function
function用来定义一个函数,让济浏览器知道有这样一个函数,但只有当函数被调用时才会执行。
定义方法如下:
function 函数名(参数表)
{
函数执行部分
}
下面举下个简单的例了来看看吧:
<html>
<head>
<title>欢迎光临</title>
<script language="javascript">
function go() //定义一个函名为go的函数
{
alert("欢迎光临")
}
</script>
</head>
<body>
<input type="button" onclick="go()" value="请点击">
<!--单击按钮调用上面定义的函数-->
</body>
</html> |
说明:
当调用函数时,所用变量或字面量均可作为变量传递。
函数由关键字Function定义。
函数名:定义自己函数的名字。
参数表,是传递给函数使用或操作的值,其值可以是常量 ,变量或其它表达式。
通过指定函数名(实参)来调用一个函数。
必须使用Return将值返回。
函数名对大小写是敏感的。