zoukankan      html  css  js  c++  java
  • 原型对象(下)

    一、原型链

    是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

    二、原型指向改变:

    • 实例对象的原型(__proto__)指向的是该对象所在的构造函数的原型对象,
    • 构造函数的原型对象(prototype)的指向如果改变了,实例对象的原型(__proto__)指向会跟着改变
       <script>
            //人的构造函数
            function Person(age){
                this.age=age;
            }
            //人的原型方法
            Person.prototype.show=function(){
                console.log("");
            }
            //学生的构造函数
            function Student(age){
             
            }
            //学生的原型方法
            Student.prototype.show=function(){
                console.log("学生");
            }
            //学生的原型方法改变,指向了人的一个实例对象
            Student.prototype=new Person(10);
            var stu=new Student();
            stu.show();//
        </script>

    三、原型最终指向

    • 对象都有一个__proto__原型,__proto__指向某个构造函数的原型prototype
    • 实例对象(__proto__)指向的是该构造函数的(prototype)
    • 该构造函数的的prototype也是一个对象,__proto__原型指向的是object的原型(prototype)
    • object的原型prototype也是一个对象,__proto__原型指向的是null
       <script>
            //人的构造函数
            function Person(age){
                this.age=age;
            }
            //人的原型方法
            Person.prototype.show=function(){
                console.log("");
            }
            var per=new Person( );
            console.log(per.__proto__==Person.prototype);//true
            console.log(Person.prototype.__proto__==Object.prototype);//true
            console.log(Object.prototype.__proto__);//null
        </script>

    四、原型指向如果改变了,那么应该在原型指向改变后添加原型方法

     <script>
            //人的构造函数
            function Person(age){
                this.age=age;
            }
            //人的原型方法
            Person.prototype.sayHi=function(){
                console.log("你好");
            }
            //改变指向----一个新对象
            Person.prototype={
                eat:function(){
                    console.log("吃饭")
                }
            }
            var per=new Person(10);//报错
            per.sayHi();
        </script>
       <script>
            //人的构造函数
            function Person(age){
                this.age=age;
            }
            //改变指向----一个新对象
            Person.prototype={
                eat:function(){
                    console.log("吃饭")
                }
            }
            //人的原型方法
            Person.prototype.sayHi=function(){
                console.log("你好");
            }
            var per=new Person(10);//你好
            per.sayHi();
        </script>

    五、举例:一个div的原型链

       <div id="dv"></div>
        <script>
            var divObj=document.getElementById("dv");
            console.log(divObj.__proto__);//HTMLDivElement
            //divObj.__proto__-------HTMLDivElement中的prototype
            //HTMLDivElement.prototype中的__proto__------Element中的prototype
            //Element.prototype中的__proto__------Node中的prototype
            //Node.prototype中的__proto__------EventTarget中的prototype
            //EventTarget.prototype中的__proto__------Object中的prototype
            //Object.prototype中没有__proto__------null
        </script>

    六、总结原型

    • 面向对象的特性:封装,继承,多态
    1. 封装就是包装,一个值存储在一个变量中,或者一堆代码放在一个函数中,或者一系列属性放在一个对象中,或者多种类似的对象放在一个js文件中
    2. 继承是一种关系,父类级别与类级别的关系,js中没有类,但是可以通过构造函数模拟类,然后通过原型来继承
    • 原型的作用之一:数据共享,目的节省内存空间
    • 原型的作用之二:为了实现继承,目的节省内存空间
       <script>
            //Person的构造函数
            function Person(name,age,sex){
                this.name=name;
                this.age=age;
                this.sex=sex;
            }
            //Person添加原型方法
            Person.prototype.eat=function(){
                console.log("吃饭");
            };
            Person.prototype.sleep=function(){
                console.log("睡觉");
            };
            Person.prototype.play=function(){
                console.log("玩球");
            };
            //Student的构造函数
            function Student(score){
                this.score=score;
            }
            //改变学生的原型的指向=========>继承人的原型方法
            //通过原型的继承,可以减少相同代码的书写,不会造成代码冗余
            Student.prototype=new Person("小明",10,"");
            //Student添加原型方法(在指向改变之后)
            Student.prototype.study=function(){
                console.log("学习");
            };
            var stu=new Student(100);
            console.log(stu.score);//100
            console.log(stu.name);//小明
            console.log(stu.age);//10
            console.log(stu.sex);//
            stu.study();//学习
            stu.eat();//吃饭
            stu.sleep();//睡觉
            stu.play();//玩球
        </script>

    七、借用构造函数继承

    • 为了数据共享,改变原型指向,做到了继承(通过改变原型指向的继承)
    • 缺陷:因为改变原型指向的同时实现的继承,直接初始化了属性,继承过来的值都是一样的
    • 解决办法就是使用借用构造函数的方法(构造函数.call(对象,属性1,属性2,......))
       <script>
            function Person(name,age,weight,sex){
                this.name=name;
                this.age=age;
                this.weight=weight;
                this.sex=sex;
                this.show=function(){
                    console.log("");
                };
            }
            Person.prototype.sayHi=function(){
                console.log("你好");
            };
            function Student(name,age,weight,sex,score){
                Person.call(this,name,age,weight,sex);
                this.score=score;
            }
            var stu=new Student("小明",18,"50kg","",100);
            console.log(stu.name);//小明
            console.log(stu.age);//18
            console.log(stu.weight);//50kg
            console.log(stu.sex);//
            console.log(stu.score);//100
            stu.show();//人(实例对象的方法可以继承)
            stu.sayHi();//报错(原型添加的方法不能继承)
        </script>

    八、组合继承

    • 借用构造函数的方法无法继承原型添加的方法
    • 解决办法是使用组合继承:原型继承+借用构造函数继承
       <script>
            //Person的构造函数
            function Person(name,age,weight,sex){
                this.name=name;
                this.age=age;
                this.weight=weight;
                this.sex=sex;
                this.show=function(){
                    console.log("");
                };
            }
            //Person原型添加的方法
            Person.prototype.sayHi=function(){
                console.log("你好");
            };
            //Student的构造函数
            function Student(name,age,weight,sex,score){
                //借用构造函数继承
                Person.call(this,name,age,weight,sex);
                this.score=score;
            }
            //原型指向改变继承原型添加的方法
            Student.prototype=new Person();
            var stu=new Student("小明",18,"50kg","",100);
            console.log(stu.name);//小明
            console.log(stu.age);//18
            console.log(stu.weight);//50kg
            console.log(stu.sex);//
            console.log(stu.score);//100
            stu.show();//
            stu.sayHi();//你好
        </script>

    九、拷贝继承:

    把一个对象中的属性或者方法,通过遍历的方法,直接复制到另外一个对象中

        <script>
            function Person(name){
                this.name=name;
            }
            Person.prototype.age=10;
            Person.prototype.sex="";
            Person.prototype.weight="60kg";
            Person.prototype.sayHi=function(){
                console.log("你好");
            };
            var obj2={};
            //Person的构造函数中有原型对象prototype,prototype就是一个对像,那么age,sex,weight,sayHi都是该对象的属性和方法
            for(var key in Person.prototype){
                obj2[key]=Person.prototype[key];
            }
            console.log(obj2.age);//10
            console.log(obj2.sex);//
            console.log(obj2.weight);//60kg
            obj2.sayHi();//你好
        </script>

    十、逆推继承看原型

        <script>
            function F1(age){
                this.age=age;
            }
            function F2(age){
                this.age=age;
            }
            F2.prototype=new F1(10);
            function F3(age){
                this.age=age;
            }
            F3.prototype=new F2(20)
            var f3=new F3(30);
            console.log(f3.age);//30
        </script>

  • 相关阅读:
    HDU 3729【二分匹配】
    51nod 1456【强连通,缩点,并查集】
    51nod1459【二级最短路】
    51nod1640 【最小生成树】
    CodeForces660B【模拟—水】
    CodeForces691C 【模拟】
    Codeforces698B【并查集+拆环】
    CodeForces717C 【数学】
    Codeforces710C【数学】
    HDU5904【瞎搞】
  • 原文地址:https://www.cnblogs.com/EricZLin/p/9062127.html
Copyright © 2011-2022 走看看