JavaScript面向对象原型链继承详解

<html>
    <head>
        <meta charset="UTF-8"/>
        <title></title>
        <script type="text/javascript">
            //目标 以最高性能完成属性和方法的继承 建议拷贝到编辑器看 黑白看的实在是难受
            //本文是对JavaScript高级程序设计面向对象的一个小总结 请先看一看书 适合对JavaScript面向对象有一定理解的人看
            //如果有误区麻烦大牛一定要指出来 不希望误人!
            //必须看懂我说的每一种方法  不要跳跃!即使你会希望你也不要跳跃 顺便帮我看看哪里说的不对
            
            //原型继承
            //这继承方法虽然属性和方法都继承了 但是一身bug 修改一个引用类型的值所有的引用类型值(不知道的话去百度)都跟着变了
            //顺便你试试SayName方法 他好使吗 为什么呢?
            //不卖关子了 对于诸位和我一样的初学者来说 我们可以这么理解:
            //Person.prototype.方法名        它是向原型链上添加一个方法
            //而Person.prototype=new 构造函数名();会对Person原型链进行破坏性的重写(也就是我们说的继承)可以理解为重装一个干净的系统 里面仅有我们继承来的方法
            //那么以前定义的SayName方法呢?当然是消失啦 一定要谨慎定义方法 一定要在重写原型链之后 否则用的时候就没了
            //但是非引用类型的值不会(修改age试试)面试可能会考引用类型 PS:顺便说一句:基础一定打好; 
            //此方法不大好 也不常用 看懂即可 我们往下看
            (function(){
                function Person(){
                    this.name='jack'
                }
                
                Person.prototype.SayName=function(){
                    alert(this.name);
                }
                
                function More(){
                    this.age=18,
                    this.color=['yellow','blue','red']
                }
                
                More.prototype.SayAge=function(){
                    alert(this.age);
                }
                
                Person.prototype=new More();
                //测试数据:取消注释即可
//                var instance1=new Person();
//                instance1.color.push('green');
//                alert(instance1.color);

//                var instance2=new Person();
//                alert(instance2.color);
            }());
            
            //借用构造函数
            //嗯 下面利用函数我们得目标完成了 属性的继承成功了,但是方法怎么办 也写进函数里??No!违背了公用方法的本意
            //如果我们方法如果写进函数里,由于函数作用域两种方法彼此看不见啊,后面的所有都用构造函数这种方法写一遍?更No
            //如果你不明白More.call(this)什么意思 仔细思考'借用构造函数实现属性继承'和下面这句话
            //将当前Person()里this指向的对象(instance)给More(),让More()里的this有和Person里的this一样的指向
            //结果代码的实际意思就变成了instance.name='jack',instance.age=18,instance.color=['yellow','blue','red']
            //如果你函数基础打的好 一定能明白的
            //而且我们调用了两次构造函数 一次是在1的位置 一次是在2 这个我们一会接着说 这句话有个印象 先忽略
            (function(){
                function Person(){
                    this.name='jack',
                    More.call(this)//2
                }
                
                
                function More(){
                    this.age=18,
                    this.color=['yellow','blue','red']
                }
                
                More.prototype.SayAge=function(){
                    alert(this.age);
                }
                Person.prototype.SayName=function(){
                    alert(this.name);
                }
                var instance=new Person();
//                var instance1=new Person();//1
//                instance1.color.push('green');
//                alert(instance1.color);

//                var instance2=new Person();
//                alert(instance2.color);
            }());
            //寄生组合式继承
            //那么有没有一种更好的形式,可以解决方法的继承呢?当然有啦 请先看代码
            //最上面的原型继承走一波!完美解决问题!不过你一定注意到了标注的1和2
            //1处通过原型继承可以继承 属性 和 方法,2处通过构造函数继承 属性,嗯 看起来没问题
            //但是我们好像用原型继承,似乎多继承了一次属性啊。。多做了一次无用功消耗了机器的性能 下面我们看看为什么会写入(调用)两次
            //1通过原型继承的时候将 属性 和 方法 写入到了原型链
            //2通过构造函数继承的时候将 属性 写入到了 原型(还记得 原型 屏蔽 原型链 吗)
            //这个时候我们进行操作是访问 原型中的属性 原型链中的方法
            //(属性和方法都是先在原型上找 在原型上找到了属性 ok 结束,在原型上没发现方法,继续找,原型链上有,ok 结束,{如果还找不到 看看Object爸爸,还没有就只能报错啦})
            
            //我们可以看一下&&&&位置的alert 依然坚挺的输出yellow,blue,red 不给你报undefined
            //因为我命令他不许访问应该访问的原型 我就想通过__proto__跳过去看看上面是否有垃圾,发现原型链上还真有 看来属性绝对被写入了两次 一次在原型上,一次原型链上
            //看来寄生组合式继承这种方法也有点业余 不过完美可用啊 不过作为一个专业的程序员是不允出现垃圾的
            
            //还有指针 请看**** 继承后原型的constructor指针为何指向了More呢,通过继承后 Person原型的constructor指针不应该指向他自己的构造函数吗
            //实际上它先指向了他自己没错 但是由于继承 它还会向上级寻找 看看有没有更多的继承(除了顶层Object对象,会忽略掉)
            //最终停在离顶层对象Object最近的那个 也就是 More
            //constructor它才没有那么智能,继承后这货看到自己家你不让它停下去看看它真正的家,它是不会停的,啥时候快撞到Object这个顶层的爸爸,它才停
            //
            (function(){
                function Person(){
                    this.name='jack',
                    More.call(this)//2
                }
                
                
                
                function More(){
                    this.age=18,
                    this.color=['yellow','blue','red']
                }
                
                More.prototype.SayAge=function(){
                    alert(this.age);
                }
                
                Person.prototype=new More();//1
                
                Person.prototype.SayName=function(){
                    alert(this.name);
                }
//                var instance1=new Person();
//                instance1.color.push('green');
//                alert(instance1.color);
//                
//                var instance2=new Person();
//                instance2.color.push('purple');
//                alert(instance2.color);
//                
//                alert(Person.prototype.constructor.name);//****
//                alert(instance2.__proto__.color);//&&&&
            }());
            (function(){
                //终极寄生组合式继承(终极完美继承)
                /* 既然寄生组合式继承会写入(调用)两次
                    那么有没有一种方法可以跳过属性直接把方法写入直接继承原型链呢?
                    当然有!我们是利用一个空构造函数作为桥梁
                    PS:当然你可以不用这个方法直接Person.prototype=More.prototype试试 (他俩共享一个原型对象还继承个什么劲。。。
                    首先我们先大概看最下面的两个函数object和inherit进行方法继承 他们两兄弟中的inherit顺手修复constructor指针 让它回家看看
                    这俩函数就不多解释了 看不懂找个豆腐撞死自己算了 稍微解释下
                    把More原型(More.prototype)上面想继承的方法,给桥梁函数bridge原型(bridge.prototype)(这时候bridge的原型指向More原型 看下一行
                                                            bridge.prototype →→→More.prototype
                    这时候该实例化一下继承啦 把bridge函数实例化顺手修复一下指针再给Person.prototype去继承
                                                        总:    Person.prototype →→→bridge.prototype →→→More.prototype
                    当当当 完成了 如果你有个小疑问 搞了半天不就是Person.prototype=new More(); 真费事 我不想看了 用上个也挺好
                    那么 如果这个被继承的对象有10个属性,100个属性呢?他被调用10次 100次呢 我们会释放多少机器的压力呢
                    
                 */
                function Person(){
                    this.name='jack',
                    More.call(this)//2
                }
                
                
                
                function More(){
                    this.age=18,
                    this.color=['yellow','blue','red']
                }
                
                More.prototype.SayAge=function(){
                    alert(this.age);
                }
                
                inherit(Person,More);
                var instance1=new Person();
                
                Person.prototype.SayName=function(){
                    alert(this.name);
                }
//                instance1.SayAge();
                
                //封装好的两兄弟函数
                function object(one){
                    function bridge(){};
                    bridge.prototype=one;
                    return new bridge();
                }
                function inherit(main,more){
                    var proto=object(more.prototype);
                    proto.constructor=main;
                    main.prototype=proto;
                }
            }());
            
        </script>
    </head>
    <body>
        
    </body>
</html>

猜你喜欢

转载自blog.csdn.net/Knoooooooow/article/details/82177700