如何理解并学习javascript中的面向对象(OOP) [转]
如果你想让你的javascript代码变得更加优美,性能更加卓越。或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件)。那么,你请务必要学习javascript面向对象,否则你无法更灵活的使用javascript这门语言。
什么事闭包?到底什么是原型?(知道闭包和原型的,就算得上是javascript的高手了。但真正能够理解,并且灵活运用的人并不多)到底该如何学习javascript中的面向对象呢?在javascript这么语言正如日中天,相信不少人正在为此而困惑。
本文中,我讲用代码+详细注释的方式,一行行一步步讲述javascript中的面向对象编程。当然有些只是我个人的理解,不足之处,敬请谅解!
1.下面部分的代码,将是从目前十分流行的JSON数据格式以及javascript数组,来一步步像大家阐述javascript中的面向对象思想。
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title>JSON数据格式</title> 5 <script src="Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script> 6 <script type="text/javascript"> 7 function jsonTest() { 8 //定义json数据格式 -- 以文本的形式存在,转换为javascript对象或者数组 9 //对象中可以包含数组,数组中也可以包含对象,可以存在相互嵌套的关系 10 var json1 = "[1,2,{a:123,b:'str',c:[100,200]}]";//数组形式 11 var parsejson1 = eval(json1);//将纯文本的内容转换为javascript原生支持的json 12 var json2 = "{name:'dinglang',age:21,hobby:['武术','电影']}";//对象形式 13 //var parsejson2 = eval(json2); //这样直接转换会报错 14 //当被eval()转换的纯文本json数据为对象形式时,需要在前后加上"()" 15 var parsejson2 = eval("(" + json2 + ")"); //这样转换就可以了 16 17 alert(""); 18 } 19 20 21 22 23 //探索一下JSON这种数据格式的由来 24 25 //1.首先是回顾一下javascript数组的相关知识 26 function arrTest() { 27 // 1)数组的基本定义与赋值 28 var arrOne = new Array(); //第一种创建方法 29 var arrTwo = new Array(0,1,2);//第二种创建方式(创建的时候就给数组赋初始值) 30 var arrThree = []; //第三种方式 --定义一个空数组 31 var arrFour = [1, 2, 3, 5]; //第四种方式--定义一个数组,并给数组赋初始值 32 //创建多维数组 33 var arrFive = new Array(1, new Array(2, 3), 4, 5); //创建一个多维数组(嵌套的) 34 var arrSix = [1, [2, 3], 4];//创建一个多维数组 35 // 2)数组的基本操作(数组是javascript语言中一种很重要的数据结构) 36 alert(arrSix[1]); //通过数组下标,来获取数组中对应的某个元素 37 arrSix[0] = 100; //给数组中下标对应的元素赋值(如果该元素还未创建,就创建该元素并赋值) 38 arrSix[99] = 888; //arrSix中会自动创建下标为99的元素,并给其赋值 --javascript中数组的长度是可以随时改变的 39 // 3)javascript当中数组常用的一些方法 40 //concat方法的使用 --可以做数组的连接或者合并,原数组的内容不变,将返回一个新的数组对象 41 var arrFour1 = arrFour.concat(101, 102, 103);//第一种连接方式 42 var arrFour2 = arrFour.concat([104, 105]);//第二种连接方式 43 var arrFour3 = arrFour.concat(arrFour1); //将已经定义的数组进行连接 44 //join方法--将数组中元素,按照指定的分隔符连接成字符串输出,原数组的内容不变 45 //slice方法--返回当前数组中的子数组,原数组中的内容不会改变 46 //push/pop 在数组的尾端追加(push)或弹出(pop),将会修改原数组的内容 47 arrFive.push(107);//在数组尾部追加一个元素 48 arrFive.pop(); //弹出数组中最后一个元素 49 //在数组的开头追加(shift)和unshift(弹出)操作 50 arrFive.reverse(); //反转数组中的元素 51 arrFive.sort(); //按照字母是顺序,对数组中的元素进行升序排列 52 arrFive.sort(function (a, b) { 53 return a - b; 54 }); //按照数值大小,进行升序排列。如果返回的是负值,那么a就会出现在b的前面 55 arrFive.sort(function (a, b) { 56 return b - a; 57 }); //按照降序排列 58 //splice 可以删除数组中一部分元素,并把部分元素进行返回。也可以在指定位置添加元素 59 var arrSplice1 = arrSix.splice(3, 2); //从下标为3的元素开始删除,删除2个元素 60 var arrSplice2 = arrSix.splice(4); //从下标为4的元素开始删除,一直删除到数组的末尾 61 arrSix.splice(1, 0, 401, 402); //在下标为1的元素前面,插入401,402这两个元素 62 arrSix.splice(1, 0[188, 189]);//在下标为1的元素前面,插入[188,199] 63 } 64 65 //2.javascript中的对象的定义、使用 66 var obj1 = new Object(); //定义一个对象 67 var obj2 = {}; //使用"{}"也可以定义一个对象 68 //给对象增加属性 69 obj1.num = 1; 70 obj1.str = "string"; 71 obj1.sayHello = function () { 72 alert("Hello"); 73 } 74 obj2.srcObj = obj1; //将obj1对象作为obj2对象的属性 75 76 //属性的访问 --第一种访问方式 77 obj1.num; //也可以这么访问 obj2.srcObj.num; 78 obj1.str; //obj2.srcObj.str; 79 obj1.sayHello(); //obj2.srcObj.sayHello(); 80 81 //属性的访问 --第二种方式 82 obj1["num"]; //obj2["srcObj"]["num"]; 83 obj1["str"]; //obj2["srcObj"]["str"]; 84 obj1["sayHello"](); //obj2["srcObj"]["sayHello"](); 85 86 //通过对象直接量的方式,定义和调用对象、属性 87 var obj3 = { 88 num: 1, 89 str: "string", 90 sayHello: function () { 91 alert('Hello'); 92 } 93 } 94 //访问方式同上,例如 95 obj3.num; //obj3["num"]; 96 97 //看清楚了吗?这就是javascript中JSON数据格式的原型 98 99 100 101 //下面来深入讲解javascript语言的面向对象特性 102 //javascript中定义类,需要用function来模拟 103 104 // function Teacher(){ 105 // 106 // } 107 //建议使用下面这种方法来创建一个类,以便将类和函数区分开来(建议定义类时首字母大写) 108 var Teacher = function () { 109 110 } 111 //定义一个book类,这里的function还承担了构造函数的工作 112 //在使用new操作符创建Book对象时,这个funtion里面的代码将会被执行一次 113 //this关键字代表的是当前对象 114 function Book(name) { 115 //定义公有的属性 116 this.name = name; 117 //定义公有的函数 118 this.getName = function () { 119 return this.name; 120 } 121 this.setName = function (nname) { 122 this.name = nname; 123 } 124 } 125 function ooTest() { 126 var tech = new Teacher(); 127 alert(tech instanceof Teacher); // instanceof函数,表示是否属于某对象类型 128 var book1 = new Book("C#");//这里的new操作相当于先创建了一个简单对象,调用了类的构造函数 129 var book2 = new Book("JAVA"); 130 alert(book1.name);//弹出C# 131 alert(book2.name);//弹出JAVA 132 book1.setName(".NET"); 133 alert(book1.name);//弹出.NET 134 alert(book2.name); //弹出JAVA 135 136 //function上面都有一个原型对象 --prototype 137 var proto = Book.prototype; 138 proto.str = "string"; 139 proto.hello = function () { 140 alert("Hello"); 141 } 142 //给原型定义了属性和方法后,拥有这个原型对象的function模拟出来的类,也具有该属性和方法 143 alert(book1.str); //弹出string 144 book1.hello(); //弹出hello 145 146 } 147 148 </script> 149 </head> 150 <body> 151 <input type="button" value="测试json" onclick="jsonTest()"/> 152 </body> 153 </html>
2.下面部分代码,是从另外一个角度讲解javascript中的面向对象编程。是借鉴EasyJF开源团队的讲解,我个人做了一些补充和说明。
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title>javascript面向对象编程</title> 5 <script src="Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script> 6 <script type="text/javascript"> 7 $(function () { 8 9 // function animal(name) { 10 // this.name = name; 11 // this.age = 0; 12 // } 13 // var a1 = animal; 14 // alert(a1);//弹出整个函数体 15 // var a2 = animal("dinglang"); 16 // alert(a2); //弹出undefined 17 // var a3 = new animal(); 18 // alert(a3);//弹出object 19 // var a4 = new animal; 20 // alert(a4);//弹出object 21 22 23 //求值 24 //alert(sum(1, 3)); //要求弹出结果为4 25 // alert(sum(1, 3, 5, 4, 7)); //要求弹出结果为20 26 //根据java或者C#的编程经验,首先想到的是函数重载。 27 // function sum(a, b) { 28 // return a + b; 29 // } 30 // function sum(a, b, c, d, e) { 31 // return a + b + c + d + e; 32 // } 33 //不幸的是,javascript并不支持函数重载。如果照上面那么写,只有下面的那个函数才会生效 34 35 //javascript支持可变参数的函数 36 function sum() { 37 38 var n = 0; 39 for (var i = 0; i < arguments.length; i++) { 40 n += arguments[i]; 41 } 42 return n; 43 } 44 45 //javascript高级知识 -- 闭包 46 //函数里面嵌套函数,且在外部被引用了,所以这个对象i不会被垃圾回收机制清除,所以i递增 47 function f1() { 48 var i = 0; 49 var f2 = function () { 50 i++; 51 alert(i); 52 } 53 return f2; //f2对象指的是整个函数体 54 } 55 var f3 = f1(); // "f1()"就是指该函数的执行结果或者返回值 --f2 56 // f3();//1 57 // f3();//2 58 // f3();//3 59 60 61 //作用域与this关键字 62 // var obj = new Object(); 63 // obj.v = "v is a object"; 64 // //相当于这么写 65 // var obj2 = { v: "v is a object" }; 66 //作用域Scope 67 var b1 = { v: "this is b1" }; 68 var b2 = { v: "this is b2" }; 69 function b(x, y) { 70 // alert(this.v + "," + x + "," + y); 71 } 72 b("ding", "lang"); //undefined,"ding","lang" 73 //调用b函数时,b函数中的this关键字指的是window对象.而Window对象中没有v对象,所以undefined 74 //window.b("ding", "lang"); //undefined,"ding","lang" --与 b("ding", "lang");意义相同 75 //b.call();//就等于b(); 76 //call函数的第一个参数表示的是函数的上下文 --表示b函数中的this 所以this关键字=b1 77 // b.call(b1, "ding", "lang"); //this is b1,ding,lang 78 //注意apply函数的用法:第一个参数表示的也是函数中的上下文。不过后面的参数要以数组的形式传递 79 // b.apply(b2, ["ding", "lang"]); // //this is b1,ding,lang 80 81 //关于作用域,再补充一点 82 var b3 = { v: "this is b3", 83 sayHello: function () { 84 alert(this.v); 85 } 86 } 87 // b3.sayHello(); //this is b3 88 //b3.sayHello.call(b1); //会调用b1对象中的sayHello函数 -- this is b1 89 90 91 // for ... in 92 // var arr = new Array(); //new 一个js数组,与c#、java等编程语言不同,可以不指定长度 93 // arr[0] = 1; //赋值 94 // arr[1] = 2; 95 // arr[2] = 3; 96 //javascript支持直接定义赋值 97 var arr = new Array(1, 2, 3); 98 for (var i = 0; i < arr.length; i++) { 99 // alert(arr[i]); //弹出 1,2 ,3 100 } 101 //注意:javascript中的for...in ,看起来与C#或者java中的foreach类似,但是不同 102 for (var key in arr) { 103 // alert(key);// 弹出0,1,2 key指的是键,而不是值。在C#的foreach中,“in”前的变量指的是值 104 //alert(arr[key]);//可以使用这种方式取值 --key指的是键,也就是某个对象中包含的所有的对象,而不是值 105 } 106 //假如我没有firebug,想使用IE实现类似与firebug控制台中console.dir的功能,可以这样 107 for (var key in window) { 108 // 这样就能将window对象中,包含的全部对象迭代显示出来。也就实现了firebug中console.dir的功能 109 //document.getElementById("key").innerHTML += (key + ":" + window[key] + "</br>"); 110 } 111 112 //对象的删除(释放内存-- 在extjs组件中常用) 113 // delete b3.v; //删除b3对象中的v成员 114 // alert(b3.v); // undefined --因为v这个成员已经被删除了 115 116 //类的修改,扩展(重点,难点) 117 //1.假如我要实现一个简单的加法计算 118 // var numOne = 5;//如果直接这么定义,那么下面的numOne.add(8);执行会报错 119 //如果我这么写,下面调用就不会报错了(因为此时的numOne,是个类.相当于java或C#语言中原始的基本数据类型、包装类型) 120 var numOne = new Number(5); 121 numOne.add = function (numTwo) { 122 return this + numTwo; 123 } 124 //alert(numOne.add); //undefined 125 // alert(numOne.add(8));//这样写看起来没错,但是会报错--numOne.add is not a function 126 var numThree = new Number(100); 127 //如果我现在想要给numThree对象中也加上add这么一个函数 128 //直接使用prototype这个特殊的属性来实现,给所有的Number类型实例都加入add函数 129 Number.prototype.add = function (numTwo) { 130 return this + numTwo; 131 } 132 133 alert(numThree.add(200).add(300)); //弹出600 100+200+300=600 134 //说明所有的Number类型确实都具有了add这么一个函数 超级延时绑定--类的扩展 135 136 //小例子 --扩展String类,给所有的String类加上sayILoveYou 137 // String.prototype.sayILoveYou = function () { 138 // alert(this.toString() + ", I Love You"); 139 // } 140 // var strOne = "dinglang"; 141 // strOne.sayILoveYou(); 142 143 //javascript中的类的用法 144 //使用构造函数的方式,定义简单的Person类(javascript函数也是一个类) 145 function Person(name, year) { 146 this.name = name; 147 this.year = year; 148 var _currentYear = 2014;//私有变量 149 150 this.nianLing = function () { 151 window.alert("原来方法:姓名:" + this.name + ",今年:" + (_currentYear - this.year) + "岁"); 152 } 153 154 this.getCurrentYear = function () { 155 return _currentYear; 156 } 157 } 158 159 Person.prototype.duoDaLe = function () { 160 window.alert("扩展方法:姓名:" + this.name + ",今年:" + (this.getCurrentYear() - this.year) + "岁"); 161 } 162 163 var p = new Person("wyp", 1981); 164 p.nianLing(); 165 p.duoDaLe(); 166 167 //实现javascript中的继承 168 169 function classA(name) { 170 this.name = name; 171 this.showName = function () { 172 alert(this.name); 173 } 174 } 175 function classB(name) { 176 //1)使用newMethod的方式实现继承 177 // this.newMethod = classA; 178 // this.newMethod(name); 179 // delete this.newMethod; //释放对象 180 //2)调用claasA这个函数,并把他的上下文(作用域)指向this(也就是classB类的实例) 181 //这样也能实现继承效果(使用call或者apply) 182 classA.call(this, name); 183 //classA.apply(this,[name]); 184 } 185 objA = new classA("操作系统"); 186 objB = new classB("组成原理"); 187 objA.showName(); //弹出“操作系统” 188 objB.showName(); //弹出“组成原理” 189 190 }) 191 </script> 192 </head> 193 <body> 194 <div id="key"> </div> 195 </body> 196 </html>
3. function,object
1 function aa() { 2 3 } 4 var bb = function () { 5 6 }; 7 var cc = new Function("a", "return a"); 8 var obj1 = new Object(); 9 var obj2 = new Array(); 10 var obj3 = {}; 11 var a = new aa();
1 function Person(name , age) { 2 this.name = name; 3 this.age = age; 4 this.show = function () { 5 window.alert(this.name); 6 } 7 this.say = say; 8 } 9 function say() { 10 window.alert(this.name); 11 } 12 Person.prototype.output = function () { 13 window.alert(this.name); 14 }; 15 var person1 = new Person("wyp",33); 16 var person2 = new Person("wyp", 33); 17 person1.say(); 18 person1.show(); 19 person1.output(); 20 window.alert(person1 instanceof Person); 21 window.alert(person1.show == person2.show); 22 window.alert(person1.say == person2.say); 23 window.alert(person1.output == person2.output);
http://blog.csdn.net/dinglang_2009/article/details/6911622