• [Object]继承(经典版)(二)原型链(原型继承)


    作者:zccst

    毫不夸张的说,这节是继承的核心所在。是重中之重。

    一、原型链——将父类的实例赋给子类的prototype

    Js代码  收藏代码
    1. function Person(name,age){  
    2.     this.name = name;  
    3.     this.age = age;  
    4.     this.arr = [11,22,33];  
    5.     this.alertName = "alertA";  
    6.     this.sayHi = function(){  
    7.         alert('hi');  
    8.     }  
    9. }  
    10.   
    11. Person.prototype.walk = function(){  
    12.     alert('walk.......');  
    13. }  
    14.   
    15. function Student(name,age,grade){     
    16.     this.grade = grade;  
    17. }  
    18.   
    19. Student.prototype = new Person();  
    20.   
    21. var s1 = new Student('xiaoming',6,3);  
    22. /* 
    23. s1.walk();//walk....... 
    24. console.log(s1.name,s1.age,s1.grade);//undefined undefined 3 
    25. console.log(s1.constructor); // Person(name,age) 
    26. */  
    27.   
    28. var s2 = new Student('xiaowang',8,6);  
    29. console.log(s1.name,s1.age,s1.grade);  
    30. console.log(s2.name,s2.age,s2.grade);  
    31. s1.alertName = "alertB";  
    32. console.log(s1.alertName);  
    33. delete s1.alertName;  
    34. console.log(s1.alertName);  
    35. console.log(s2.alertName);  
    36. s1.arr.push(55);  
    37. console.log(s1.arr);  
    38. console.log(s2.arr);  
    39.   
    40.   
    41.   
    42.   
    43.   
    44.   
    45. Student.prototype.study = function(){  
    46.     alert('I am study');  
    47. }  
    48. var p1 = new Person();  
    49. //p1.study();// p1.study is not a function  


    缺点:虽然s1仍然指向父类的构造函数,但修改子类的共有方法并不会对父类有所影响,但是存在一个更为严重的问题是,子类没法继承父类的特权属性和特权方法。





    二、原型链与call组合





    三、原型继承的其他实现方式
    1,直接将父类的prototype赋给子类的prototype
    缺点:父类与子类耦合太高,因为改动了子类的prototype会影响父类。即使将原型对象的constructor指向子类构造函数,但子类和父类的实例都会共有相同的constructor,这种情形下修改子类的共有方法,同时会修改了父类的共有方法,说明此法不通。

    Js代码  收藏代码
    1. function Person(name,age){  
    2.     this.name = name;  
    3.     this.age = age;  
    4.     this.sayHi = function(){  
    5.         alert('hi');  
    6.     }  
    7. }  
    8. Person.prototype.walk = function(){  
    9.     alert('walk.......');  
    10. }  
    11. function Student(name,age,grade){   //子类  
    12.     this.grade = grade;  
    13. }  
    14. Student.prototype = Person.prototype;  
    15.   
    16. var s1 = new Student('xiaoming', 6, 3);  
    17. s1.walk();//walk.......  
    18. console.log(s1.name, s1.age, s1.grade);//undefined undefined 3  
    19. console.log(s1.constructor); // 就是Person构造函数 Person(name,age){...}  
    20.   
    21. //主要缺陷:不能继承父类的特权属性和特权方法,子类的构造函数变成了Person(name,age),直接导致修改子类的原型方法时,父类也跟着修改了,耦合度太高了。  
    22. Student.prototype.study = function(){  
    23.     alert('I am study');  
    24. }  
    25. var p1 = new Person();  
    26. p1.study();//I am study  






    2, niubility方式-利用空函数实现继承 
    优点:这种情况下修改Student的prototype就不会影响到Person的prototype对象了,并且,因为直接将Person的 prototype赋给Empty的prototype,所以不会存在特权属性(实例属性)浪费资源的问题。这样利用空函数就能很好的解决共有方法的继承 问题了。当然这时Student.prototype中的constructor是Person,所以最好加上 Student.prototype.constructor = Student转换过来。

    Js代码  收藏代码
    1. function Person(name,age){  
    2.     this.name = name;  
    3.     this.age = age;  
    4. }  
    5. Person.prototype.sayHi=function(){  
    6.     alert('hi');  
    7. }  
    8.   
    9. function Student(name,age,grade){  
    10.     Person.call(this,name,age);  
    11.     this.grade = grade;  
    12. }  
    13.   
    14. function Empty(){  
    15. }  
    16. Empty.prototype = Person.prototype;  
    17.   
    18. Student.prototype = new Empty();  
    19. Student.prototype.constructor = Student;//特别关键的一句  
    20. Student.prototype.sayGrade=function(){  
    21.     alert(this.grade);  
    22. }  
    23.   
    24. var p1 = new Person('xiaoming',10);  
    25. var s1 = new Student('xiaohong',9,3);  
    26. console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}  
    27. console.log(s1);//Student {name="xiaohong", age=9, grade=3, 更多...}  
    28. console.log(p1.constructor);//Person(name,age) 父类的实例指向仍是父类  
    29. console.log(s1.constructor);//Student(name,age,grade) //子类的实例指向仍是子类  
    30.   
    31.   
    32.   
    33. //以下是错误的  
    34. Student.prototype.study = function(){  
    35.     alert('I am study');  
    36. }  
    37. var o1 = new Person();  
    38. o1.study();//错误  
    39. var e1 = new Empty();  
    40. e1.study();//错误  








    3,利用循环遍历拷贝的方法实现继承(循环将父类原型对象赋给子类原型对象)
    for(var i in Person.prototype){
    Student.prototype[i] = Person.prototype[i];
    }
    Student.prototype.constructor = Student;*/

    优点:
    父类原型对象的constructor指向父类构造函数,
    子类原型对象的constructor指向子类构造函数,

    这种循环方式,跟父类的实例属性和方法,没有任何关系,所以继承的实现用Call。

    Js代码  收藏代码
    1. function Person(name,age){  
    2.     this.name = name;  
    3.     this.age  = age;  
    4.     this.sayName = function(){  
    5.         alert(this.name);  
    6.     };  
    7. }  
    8. Person.prototype.sayAge = function(){  
    9.     alert(this.age);  
    10. }  
    11.   
    12. function Student(name,age,grade){  
    13.     Person.call(this, name, age);  
    14.     this.grade = grade;  
    15. }  
    16. //循环copy方式继承  
    17. for(var i in Person.prototype){  
    18.     alert(i);//只循环了一次,就是将父类原型方法sayAge赋给子类原型对象  
    19.     Student.prototype[i] = Person.prototype[i];  
    20. }  
    21. //批注:for in只循环自定义的prototype对象属性和方法,所以并不会修改constructor指针指向  
    22.   
    23. //继续添加方法  
    24. Student.prototype.sayGrade = function(){  
    25.     alert(this.grade);  
    26. }  
    27.   
    28. var s1 = new Student("zheng", 30, 3);  
    29. console.log(s1);  
    30. console.log(s1.constructor);  
    31. s1.sayGrade();  
    32.   
    33. var p1 = new Person("aliali", 50);  
    34. console.log(p1);  
    35. console.log(p1.constructor);  
    36. //p1.sayGrade();  


    其实,父类和子类是没有任何关系的,唯一的联系是子类的prototype

  • 相关阅读:
    编译Excel遇到的DialogBoxW宏的实参不足问题
    C# 简单连接数据库并执行SQL查询语句
    AutoCAD VBA 遍历所有对象
    VBA: 错误消息:"类未注册"插入用户窗体
    解决Qt程序发布时中文乱码问题
    Qt操作excel
    HWND_BROADCAST的一个用法——修改环境变量,立即通知系统
    VC环境使用XML解析器(TinyXML)编程
    C++ XML解析之TinyXML篇(转载)
    C/C++枚举目录中的文件或文件夹
  • 原文地址:https://www.cnblogs.com/shsgl/p/4289900.html
Copyright © 2020-2023  润新知