上一主题下一主题
«12345»Pages: 1/16     Go
关键字
主题 : JavaScript OOP你现在还不懂,真OUT了!
级别: VIP四级

UID: 230365
精华: 12
发帖: 314
威望: 3432 点
学点: 380 点
贡献: 2 点
好评: 1 点
学币: 0 个
注册时间: 2010-04-16
最后登录: 2014-09-25
楼主  发表于: 2014-05-06 15:50||

1 JavaScript OOP你现在还不懂,真OUT了!

管理提醒: 本帖被 zylzyl 设置为精华(2014-05-07)
全面深入J****aScript OOP面向对象编程(史上最全面通俗易懂):点此了解详情
'JO}6 ;W  
LWxP}? =  
Bw<$fT`  
        前段时间,认识的一学生,已经工作了近三年,J****a,.net都有****过****发,去淘宝面试,回来后跟我聊,很受打击,说面试他的人其他的问的不多,就是对他的J****aScript语言感兴趣,但问他的即不是Jquery,也不是EasyUI,ExtJs等富客户端的东西,直接问JS最原生的特性及JS OOP相关的东西,他搞了这么多年****发,平时对jquery用的很熟,对JS基本会用,遇到效果了,网上找找,拿过来修修改改,凑合能用就行,至于JS的OOP,什么封装,闭包,原型链,JS的继承等几乎是一点也不懂,结果面试的结果可想而知了。 Z1h6Y>j  
ZftucD|ZY/  
      其实,听完他讲这些,我一点都不觉得奇怪,现在的软件****发逐渐向B/S端,移动****发方向发展,但不管哪个方向,如果要想****出一些高性能,高质量的程序,几乎对JS都会有着很高的要求,会一点JS对于普通 ****网站可能就够用了,但是如果涉及到用户对体验要求很高,浏览器的兼容性要求高及一些特殊的领域如:GIS,自主****发工作流,绘制线路图等方面应用时,对JS的要求肯定会是相当高,而且这类人员的工资待遇也会相当高,****一个Web****发高手,或者是一个Web****发的老鸟的话,也一定会是要求对JS非常精通,而精通的前提就是要求理解并会使用JS OOP进行客户端技术****发。 Y3ypca&P9  
;xSlRTNT=6  
        本人有幸在10年前就从事过纯客户端产品的****发,很早接触JS及JS OOP,对这方面有一些自己的研究和心得,感觉网上这方面的资料虽然很多,但不系统,不完整,不成体系,接下来,我想快速的整理一下网上资料,让很多从来没有接触过JS OOP概念的朋友们,快速了解什么是JS OOP, 它的封装、继承、多态是怎么实现的,****一个扫盲。 Ko!a`I2M}  
;[7#h8  
一、你必须知道的 'N&s$XB,  
1) 字面量 @sRb1+nn  
2) 原型 }5d|y*  
3) 原型链 Of  nN  
4) 构造函数 >`n)-8  
5) 稳妥对象(没有公共属性,而且其方法也不引用this的对象。稳妥对象适合用在安全的环境中和防止数据被其它程序改变的时候) V.!z9AQ  
}]pOR&o  
二、****始创建对象吧 t&C0V|s79$  
<1>: 首先来看两种最基本的创建对象的方法 G[ q<P  
1> 使用Object创建对象 kqCUr|M.P  
复制代码
  1. var o = new Object();
  2. o.sname = 'JChen___1';
  3. o.showName = function(){
  4.     return this.sname;
  5. }
@iVEnb.'  
2> 使用对象字面量创建对象 <2\Q Y  
复制代码
  1. var o = {
  2.     name: 'JChen___2',
  3.     getName: function(){
  4.         return this.name;
  5.     }
  6. }
^izf&W.j!  
但是这两个方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。 WWA!_  
'fIG$tr9X  
<2> 接下来看看几种创建对象的模式吧 ?o(Y\YJf  
1>工厂模式 MENrP5AL  
"; ?^gA  
复制代码
  1. function create(name){
  2.     var o = new Object();
  3.     o.name = name;
  4.     o.sayName = function(){
  5.         return this.name;
  6.     };
  7.     return o;
  8. }
  9. var p1 = create('JChen___');
7v(<<>  
*%dWNvN4X  
工厂模式也有一个缺点:就是没有解决对象识别的问题(即怎样知道一个对象的类型)。 Z?'?+48xv4  
6 wD  
2> 构造函数模式 f q*V76F  
PLWx'N-kqL  
复制代码
  1. function create2(name){
  2.     this.name = name;
  3.     this.sayName = function(){
  4.         return this.name;
  5.     };
  6.     //this.sayName = sayName;
  7. }
  8. //function sayName(){ return this.name};
  9. var p1 = new create2('JChen___4');
ulXe;2  
N4, !b_1  
构造函数模式也有一个缺点:就是每个方法都要在每个实例上创建一遍。 YifTC-Q;  
当然我们可以用上面的两行注释掉了代码来屏蔽上面那个缺点。 ^^(4xHN  
但是……,我们又产生了一个新问题——全局变量。如果有很多方法,我们岂不是要定义很多个全局变量函数。这是个可怕的问题。 /7b$C]@k  
7/Mhz{o;W  
3> 原型模式 r)Iq47Uiw  
1) 普通方法 [M:BJ%*  
复制代码
  1. function create3(){}
  2. create3.prototype.name = 'JChen___5';
  3. create3.prototype.sayName = function(){
  4.     return this.name;
  5. };
  6. var p1 = new create3();
+|Qe/8Q  
UyOoyyd.  
2) 原型字面量方法——我姑且这么称吧 FuO'%3;c  
}!Xj{Eoc  
复制代码
  1. function create3(){}
  2. create3.prototype = {
  3.     constructor: create3, //我们要设置它的constructor,如果它很重要
  4.     name: 'JChen___5',
  5.     sayName: function(){
  6.         return this.name;
  7.     }
  8. };
  9. var p1 = new create3();
C9 cQ} j:  
,:/3'L  
原型的缺点: 3Y=?~!,Jk  
1): 不能传参 rKWkT"  
2): 共享了变量 24/ ^_Td  
@c{ b\is2  
4> 构造+原型(模式) U*Pi%J  
m_1BB$lyP2  
复制代码
  1. function create4(name){
  2.     this.name = name;
  3. }
  4. create4.prototype.sayName = function(){
  5.     return this.name;
  6. }
  7. var p1 = new create4('JChen___6');
Q u@T}Ci  
这种模式是目前使用最广泛、认同度最高的一种创建自定义类型的方法。 ( cqVCys  
5J<ghv>\P  
5> 动态原型模式 @C6.~OiP  
+0WI;M4i  
复制代码
  1. function create5(name){
  2.     this.name = name;
  3.     if(typeof this.sayName != 'function'){
  4.         create5.prototype.sayName = function(){
  5.             return this.name;
  6.         }
  7.     }
  8. }
  9. var p1 = new create5('JChen___7');
XqTDLM&  
~!W{C_*N  
这种方法确实也是十分完美的一种方法。 AIFI@#3  
B@2VI 1%  
6> 寄生构造函数模式 Kdwt^8Umh  
7{e*isV  
复制代码
  1. function create6(name){
  2.     var o = new Object();
  3.     o.name = name;
  4.     o.sayName = function(){
  5.         return this.name;
  6.     }
  7.     return o;
  8. }
  9. var p1 = new create6('JChen___8');
/__@a&9t  
[Dq!t1  
注意那个return o。构造函数在不返回值的情况下,会返回新对象实例。而通过在构造函数的末尾加入return 语句,可以重写调用构造函数时返回的值。 J-g<-!>RM  
这个种用法可以用在,假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改Array的构造函数,因此可以使用这个模式。 Th)Z?\8zk  
i>68gfx  
复制代码
  1. function specialArray(){
  2.     var values = new Array();
  3.     values.push.apply(values, arguments);
  4.     values.join2 = function(){
  5.         return this.join('|');
  6.     };
  7.     return values;
  8. }
  9. var colors = new specialArray('red', 'blue', 'green');
  10. colors.join2();//returned: red|blue|green
Sq,x57-  
^p 4 33  
7>稳妥构造函数模式 !nkjp[p  
稳妥构造函数遵循与寄生构造函数类似的模式,但是有两点不同: N8^ AH8l  
一是新创建对象的实现方法不引用this Qs5^kddz=  
二是不使用new操作符调用构造函数。  iFy_ D  
d}t7bgk'j  
复制代码
  1. functioncreate7(name){
  2.     var o = new Object();
  3.     var age = 12;                //私有变量
  4.     o.sayName = function(){      //私有方法
  5.         return name + ' ' + age;
  6.     }
  7.     returno;
  8. }var p1 = create7('JChen___9');
yy%'9E ldc  
_c 4kj  
二、JS继承的6种方法 x2bKFJ>e@  
1> 原型链继承 !w8t`Z['  
原型链继承是通过创建Super的实例,并将该实例赋值给Sub.prototype来实现的。 6RLYpQ$+  
实现的本质是:重写子类型的原型对象,代之以超类型的实例。 ~S,R`wo  
? 2#MU  
复制代码
  1. function Super(){
  2.     this.name = 'JChen___';
  3. }
  4. Super.prototype.getSuperName = function(){
  5.     return this.name;
  6. }
  7. function Sub(){
  8.     this.subname = 'JChen___son';
  9. }
  10. Sub.prototype = new Super(); //原型继承体现在这里
  11. Sub.prototype.getSubName = function(){
  12.     return this.subname;
  13. }
  14. var instance = new Sub();
N1 }#6YNw  
+ q/ j  
注意:此时instance.constructor现在指向的是Super的,这是因为Sub.prototype指向了Super.prototype,而Super.prototype.constructor = Super。 dyz)22{\!`  
原型链的问题:类似于利用原型创建对象,原型共享的特性也是原型链继承的最大问题。 Pu=,L#+FN  
""JTU6]MS  
2> 借用构造函数继承 >vPDF+u  
在解决原型中包含引用类型值所带来的问题的过程中,我们****始使用一种叫****借用构造函数的技术。 Az}.Z'LJ  
这种技术的基本思想相当简单:在子类型构造函数的内部调用超类型构造函数。 O#g'4 S  
这样一来,就会在新子类对象上执行超类函数中定义的所有对象初始化代码。结果,每个子类的实力都会有自己的超类中属性的副本了。 q`l%NE  
\L"Vx9xT  
复制代码
  1. function Super2(name){
  2.     this.colors = ['red', 'blue'];
  3.     this.name = name;
  4. }
  5. function Sub2(){
  6.     Super2.call(this, 'JChen___2'); //借用构造函数技术体现在这里
  7.     this.age = 29;
  8. }
  9. var instance1 = new Sub2();
  10. instance1.colors.push('black');
  11. var instance2 = new Sub2();
  12. instance2.colors.push('green');
i*We kr3Wo  
*,:>EcDr  
借助构造函数继承的问题: ?~vVSY  
1): 方法都在构造函数中定义,无法复用。 qW1d;pt  
2): 在超类型的原型中的方法对子类是不可见的。 <,r|*pkhp~  
rff=ud>Jf  
3> 组合继承(原型+借用构造) [\ M$a|K  
组合继承指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。 aL9 yNj}2  
组合继承的思路:使用原型链实现对方法和属性的继承,通过借用构造函数实现对实例属性的继承。 lTe7n'y^^  
b'!t\m  
复制代码
  1. function Super3(name){
  2.     this.name = name;
  3.     this.colors = ['red', 'blue'];
  4. }
  5. Super3.prototype.sayName = function(){
  6.     return this.name;
  7. }
  8. function Sub3(name, age) {
  9.     Super3.call(this, name);
  10.     this.age = age;
  11. }
  12. Sub3.prototype = new Super3(); //解决借用构造函数技术的缺点
  13. Sub3.prototype.constructor = Sub3; //纠正原型继承改变了的构造函数
  14. Sub3.prototype.sayAge = function(){
  15.     return this.age;
  16. }
`OL@@`'^{S  
-|ho 8alF  
组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为J****aScript中最常用的继承模式。 raWs6b4Q  
组合继承的问题:两次调用超类构造函数。 0W92Z@_GY  
1G0U}-6RH  
4> 原型式继承 eI+<^p_j2  
原型式继承的思路:借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。 SXYH#p  
c>_tV3TDA  
复制代码
  1. function object(o){ //原型式继承的关键
  2.     function F(){}
  3.     F.prototype = o;
  4.     return newF();
  5. }
  6. var person = {
  7.     name: 'JChen___4',
  8.     colors: ['blue']
  9. }
  10. var person1 = object(person);
  11. person1.name = 'JChen___4___2'person1.colors.push('red');
  12. var person2 = object(person);
  13. person2.name = 'JChen___4___3';
  14. person2.colors.push('green');
RZ(*%b<C  
2 L>;M  
原型式继承的问题:同原型链一样,他也有共享的劣势。 F/ZB%;O9  
uwQ~4   
5> 寄生式继承 S}O>@ %  
寄生式继承的思路:创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后再返回该对象 9j0Hvo%T  
))/NGa  
复制代码
  1. function createAnother(origin){ //寄生式继承的关键
  2.     var clone = object(origin);
  3.     clone.sayHi = function(){
  4.         return 'Hi';
  5.     };
  6.     return clone;
  7. }
  8. var person = {
  9.     name: 'JChen___4',
  10.     colors: ['blue']
  11. }
  12. var person1 = createAnother(person);
eGwO!Lv}B  
?IKSSe#,  
寄生式继承的问题:像构造函数一样,由于不能****到函数的复用而降低效率。 -6Y@ _N  
DjyqQ yq~  
6> 寄生组合式继承 \k DQ[4mGq  
寄生组合式继承:通过借用构造函数来借用属性,通过原型链的混成形式来继承方法。 P3 Wnso  
其背后的思想是:不必为了指定子类型的原型而调用超类型的构造函数,我们需要的无非就是超类型的一个副本而已。 L701j.7"  
v qt#JdPp9  
复制代码
  1. function object(o){
  2.     function F(){}
  3.     F.prototype = o;
  4.     return new F();
  5. }
  6. function inheritProto(subType, superType){ //避免第一调用构造函数的关键
  7.     var proto = object(superType.prototype);
  8.     proto.constructor = subType;
  9.     subType.prototype = proto;
  10. }
  11. function Super6(name){
  12.     this.name = name;
  13.     this.colors = ['red', 'blue'];
  14. }
  15. Super6.prototype.sayName = function(){
  16.     return this.name;
  17. }
  18. function Sub6(name, age){
  19.     Super6.call(this, name);
  20.     this.age = age;
  21. }
  22. inheritProto(Sub6, Super6);
  23. Sub6.prototype.sayAge = function(){
  24.     return this.age;
  25. }
  26. var instance1 = new Sub6('JChen___6', '12');
  27. instance1.colors.push('black');
CIxa" MW  
1@dB*Jt  
****发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。 )8cb @N  
三、总结 b< dwf[  
这就是J****aScript中的6种继承方式,如果大家能够画出每个继承的原型链关系图,那么继承就是小菜一碟了 eD|p1+76  
了解了这些,你基本上对OOP有了一个入门,补充说明,以上内容均来自互联网,非本人原创。不过可能对于JS OOP重来没有接触过的同学看起来还是会觉得有些吃力,我最近也在整理这方面的资料并录制相关方向的课程,目录列下:  i/vo  
复制代码
  1. 1. part1_c05_01_01_前言-为什么你要学习J****aScript2. part1_c05_01_02_JS****发神器-WebStorm高级使用技巧
  2. 3. part1_c05_01_02_使用方括号([ ])引用对象的属性和方法
  3. 4. part1_c05_01_03_Web浏览器中J****aScript调试技巧
  4. 5. part1_c05_02_01_用定义函数的方式定义类
  5. 6. part1_c05_02_02_使用new操作符获得一个类的实例
  6. 7. part1_c05_02_03_动态添加、修改、****JS对象的属性和方法
  7. 8. part1_c05_02_04_使用大括号({ })语法创建无类型对象
  8. 9. part1_c05_02_05_prototype原型对象
  9. 10. part1_c05_03_01_初识j****ascript函数对象
  10. 11. part1_c05_03_02_函数对象和其他内部对象的关系
  11. 12. part1_c05_03_03_将函数作为参数传递
  12. 13. part1_c05_03_04_传递给函数的隐含参数_arguments
  13. 14. part1_c05_03_05_函数的apply、call方法的运用
  14. 15. part1_c05_03_06_深入认识J****aScript中的this指针
  15. 16. part1_c05_04_01_理解j****ascript中类的实现机制
  16. 17. part1_c05_04_02_使用prototype对象定义类成员
  17. 18. part1_c05_04_03_J****aScript类的设计模式优化
  18. 19. part1_c05_05_01_J****aScript类的公有成员与私有成员
  19. 20. part1_c05_05_02_J****aScript类的静态成员
  20. 21. part1_c05_06_01_在J****aScript中利用for(…in…)语句实现反射
  21. 22. part1_c05_06_02_JS中利用反射动态设置CSS样式高级技巧
  22. 23. part1_c05_07_01_利用共享prototype实现继承的用法与缺陷
  23. 24. part1_c05_07_02_利用反射机制和prototype实现JS继承
  24. 25. part1_c05_07_03_参考prototype.js框架自实现JS中的类的继承
  25. 26. part1_c05_07_04_Prototype.js源码剖析与使用示例
  26. 27. part1_c05_08_01_在J****aScript中实现抽象类与虚方法
  27. 28. part1_c05_08_02_J****aScript中使用抽象类的示例
  28. 29. part1_c05_09_01_自定义实现JS中最简单的事件设计模式
  29. 30. part1_c05_09_02_重构自定义J****aScript事件****程序解决事件传参问题
  30. 31. part1_c05_09_03_重构自定义J****aScript事件****程序多事件绑定机制
  31. 32. part1_c05_10_01_J****aScript面向对象综合示例
  32. 33.part1_c05_11_01_JS压缩与混淆工具(JSA、JSCompressor、Google Closure Compiler )
  33. 34. part1_c05_11_02_JS高级调式工具(FireBugLite)
yt'P,m  
学完这套课程你能得到东西: syJLcK+e  
想学习JS的调试,性能优化,及一些优秀前端工具的使用 $ Jz(Lb{  
对JS的应用有更深层次了解 LD=eMk: ~  
对JS OOP思想有一定程度的了解 v)b_bU]Hx  
自己能动手写一个基于JS OOP的简单框架 5*O*p `Ba  
对于后继jquery,easyui,extjs等富客户端的学习打好基础 NJNS8\4  
能用于J****a,PHP,.NET****发,移动****发工作中 _VUG!?_D$5  
上述课程的录制正在进行中,欢迎大家多对课程提宝贵意见,以****内容,早日出来,以飨读者。 U<YcUmX  
另附:已经讲完的部分内容,大家可以下载下来看下,以加深对JS OOP的理解 J dM0f!3  
附下载: F@tfbDO?  
5. part1_c05_02_01_用定义函数的方式定义类 9\zasa  
6. part1_c05_02_02_使用new操作符获得一个类的实例 %eE0a4^".  
7. part1_c05_02_03_动态添加、修改、****JS对象的属性和方法 2 rFjYx8D!  
8. part1_c05_02_04_使用大括号({ })语法创建无类型对象 RoFOjCc>D.  
9. part1_c05_02_05_prototype原型对象 (GW"iL#.  
10. part1_c05_03_01_初识j****ascript函数对象 /E39Z*  
11. part1_c05_03_02_函数对象和其他内部对象的关系 ? K,d  
12. part1_c05_03_03_将函数作为参数传递 mo?*nO|-  
13. part1_c05_03_04_传递给函数的隐含参数_arguments 3'7]jj  
14. part1_c05_03_05_函数的apply、call方法的运用 Ud_7>P$a  
15. part1_c05_03_06_深入认识J****aScript中的this指针 ~.<QC<dN  
链接: http://pan.baidu.com/s/1pJv09ib h6Q~Di  
密码:
本部分内容设定了隐藏,需要回复后才能看到
cBD#F$K2  
7BS5Eq B=  
全面深入J****aScript OOP面向对象编程(史上最全面通俗易懂):点此了解详情
级别: VIP五级

UID: 464190
精华: 0
发帖: 1
威望: 8 点
学点: 13 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2014-05-07
最后登录: 2015-06-24
沙发(1楼)  发表于: 2014-05-07 19:27||

very very thank you
级别: 北风技术员

UID: 223452
精华: 0
发帖: 55
威望: 534 点
学点: 4 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2010-03-16
最后登录: 2014-05-10
板凳(2楼)  发表于: 2014-05-10 23:08||

楼主写的很好,学习了
级别: VIP四级

UID: 260541
精华: 0
发帖: 44
威望: 394 点
学点: 15 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2010-09-16
最后登录: 2015-04-26
地板(3楼)  发表于: 2014-05-11 00:56||

非常好啊,顶
级别: 终身会员

UID: 8195
精华: 0
发帖: 129
威望: 612 点
学点: 46 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2008-06-13
最后登录: 2015-06-06
地下室(4楼)  发表于: 2014-05-11 18:05||

看看啊看卡看
级别: 终身会员

UID: 8195
精华: 0
发帖: 129
威望: 612 点
学点: 46 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2008-06-13
最后登录: 2015-06-06
下水道(5楼)  发表于: 2014-05-11 20:19||

老师的发布计划 怎么的?
级别: VIP四级

UID: 230365
精华: 12
发帖: 314
威望: 3432 点
学点: 380 点
贡献: 2 点
好评: 1 点
学币: 0 个
注册时间: 2010-04-16
最后登录: 2014-09-25
6楼  发表于: 2014-05-12 13:33||

计划会是6月份和我的一套大型的商业课程“基于ASP.NET MVC 4 +Knockout.JS+Web API+FluentData+EasyUI 技术实现Web通用商业****发框架” 官网预****,到时这门课程也会单独拿出来****,请大家关注北风论坛,谢谢各位的支持
级别: 北风爱好者

UID: 464854
精华: 0
发帖: 2
威望: 4 点
学点: 6 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2014-05-13
最后登录: 2014-08-04
7楼  发表于: 2014-05-13 12:05||

很好很强大 我喜欢。
级别: 北风爱好者

UID: 424923
精华: 0
发帖: 1
威望: 2 点
学点: 2 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2013-05-31
最后登录: 2014-05-13
8楼  发表于: 2014-05-13 15:47||

看看 thank you very much
级别: 北风爱好者

UID: 465177
精华: 0
发帖: 1
威望: 2 点
学点: 4 点
贡献: 0 点
好评: 0 点
学币: 0 个
注册时间: 2014-05-15
最后登录: 2014-05-15
9楼  发表于: 2014-05-15 18:27||

我是来拿资源的,嘻嘻
上一主题下一主题
«12345»Pages: 1/16     Go