菜鸟新手taob 2011-09-19
先来讲讲静态类数组(类数组): JavaScript是一个弱类型的语言,但是我们可以通过不同的方式来侧面的实现类的创建,不管是工厂函数、函数原型还是静态类,均可实现模拟类,每一种都有它的特点。 静态类数组即是建立在静态类的基础上实现的数组模型。 var class = { name : "object", color : "red" } 以上是创建了一个静态类class,我们知道,调用类的成员有两种方式 点号形式:class.name 索引形式:class["name"] 其中索引形式与数组的形式非常相像,我们不妨设计一个如下样式的静态类: var LikeArray = { 0 : "A", 1 : "B", 2 : "C" } 如果现在我用索引的形式来调用类的成员属性0,1,2,即LikeArray[0]、LikeArray[1],这样便与数组对象十分相似,唯一的区别就是没有length属性(我们可以通过添加length成员来模拟length属性)。 注:只有静态类的成员名才能以纯数字来命名,调用成员若为纯数字命名则可以省略双引号。 我们先把上面讲的放一放,来看一个别的函数——apply: apply是一个特殊又十分有用的东西,它的作用是可以改变当前作用对象的方法内this指针指向另一个对象。 语法为:[对象.]方法.apply(另一个对象[,参数数组]); 如: var one = function(){ this.arr = ["a","b","c"]; this.show = function(){ alert(this.arr); } } var two = function(){ this.arr = ["d","e","f"]; } var obj = new one(); obj.show.apply(new two()); //使用one对象的show方法但其内部this却指向了two对象,因此会弹出d,e,f 以上也可以说明,apply使two对象继承了one对象的成员属性或方法并立即使用。 下面,我们结合静态类和apply动态生成静态类数组: var obj = { length : 0 //① } var arr = ["a","b","c","d","e"]; //定义数组并初始化 [].push.apply(obj,arr); // ② alert(obj[1]); //Debug,弹出b ①这里仿照数组,模拟设置了一个length属性(必须,后面介绍) ② []表示数组对象,等同于new Array(),通过apply使obj类继承Array类的push方法并使用,同时给push方法传入参数arr。整体效果即为,将数组arr强行压入obj类,使它成为类似于如下的形式: var obj = { length : 0, 0 : "a", 1: "b", 2: "c", …… } 注:由于push方法有一个关联属性——length,push每一个数组元素,length都会自动加一,因此length不可缺少,我们为静态类obj特意加上length属性,这样[].push.apply(obj,arr);才能正常运行。 这样,整个静态类数组(类数组)简单的实现就完成了,用处不是很多,基本是用在Javascript框架(库)中去,其中jQuery库也牵扯到此内容。下面,我们就制作一个简单Js框架(类似于Jquery),功能虽简单,只要大家勤动手动脑,为这个小小的框架扩展,就可以完成一个属于自己的js库。 /* Your JavaScript Framework */ var fw = $ = window.$ = window.fw = function(selector){ return new fw.fn.init(selector); //fw对象以静态类数组形式存在,生成的实际是init的实例 } fw.fn = { //新的命名空间名fw.fn setArray : function(arr){ //生成fw对象的类数组 this.length = 0; // 模拟length属性初始化 [].push.apply( this, arr ); // 继承数组对象push方法 }, init : function(selector){ var d=[]; //定义一个临时的DOM数组,用来存储DOM对象 if(selector.indexOf("#")== 0){ //获取一个ID元素 d[0]=document.getElementById(selector.substr(1)); // 唯一性的ID元素赋予d[0]即可 } else if(selector.indexOf(".")== 0){ //获取指定Class元素集合 var j=0; var A = document.getElementsByTagName('*'); // 以下均为获取class算法 for (var i=0; i< A.length; i++ ) { if (A.className == selector.substr(1) ) { d[j++] = A; } } } else{ //获取标签元素集合 d=document.getElementsByTagName(selector); // 标签是一个集合,因此可以直接赋予临时数组d保存 } var arr = []; // 定义空数组 for(var i=0; i<d .length; i++){ //遍历临时数组d arr.push(d); //将d中的DOM元素依次压入数组arr中 } d = null; //释放临时DOM数组 return this.setArray(arr); // 返回类数组对象 }, html : function(value){ if(typeof(value)=="undefined"){ //如果参数为空,则说明是读取内容 return this[0].innerHTML; // this[0]的目的是将fw对象转换成DOM对象,以便使用innerHTML方法 } else{ this[0].innerHTML=value; //关于对象转换将在以后的文章中介绍,如果这篇原理了解了相信大家会自己明白 } return this; //返回fw对象,可以实现连写 } } fw.fn.init.prototype = fw.fn; // 将fw.fn内的所有成员复制给init,这样new出来的init对象才能使用自己框架的方法 现在我们开始调试: <div id="a">Hello </div> <p class="b"> My </p> <span> Framework<span> <script language="javascript"> var s = $("#a").html() + $(".b").html() + $("span").html(); // fw框架选择器,调用我们的html方法 alert(s); $("#a").html("Welcome "); // 有参数的html方法可以修改内容 </script>