资讯专栏INFORMATION COLUMN

理解JS构造函数继承

ninefive / 2216人阅读

摘要:对象之间的继承有以下几个方法用和不推荐多带带使用,定义在中的属性和方法不能继承模式注意需要先继承后定义传统模式推荐,关键点是以及重新改变利用空对象间接继承只继承中的属性,关键点在于利用一个空的构造函数当中介拷贝继承不推荐多带带使用,循环逐一拷贝

对象之间的继承有以下几个方法:

用call和apply(不推荐多带带使用,定义在prototype中的属性和方法不能继承)

prototype模式(注意prototype需要先继承后定义)

传统prototype模式(推荐,关键点是Child.prototype = new Parent.prototype以及重新改变Child.prototype.constructor)

利用空对象间接继承(只继承prototype中的属性,关键点在于利用一个空的构造函数当中介)

拷贝继承(不推荐多带带使用,for循环逐一拷贝)

以上推荐使用传统prototype模式以及call和apply与拷贝继承相配合的模式

用call和apply

</>复制代码

  1. function Chinese() {
  2. this.nationality = "Chinese";
  3. }
  4. function Person(name, age) {
  5. Chinese.apply(this); //这里改变了Chinese中this的指向
  6. this.name = name;
  7. this.age = age;
  8. }
  9. var p1 = new Person("Oli", 18);
  10. console.log(p1.nationality); //Chinese

传统prototype模式

</>复制代码

  1. function Chinese() {
  2. this.nationality = "Chinese";
  3. }
  4. function Person(name, age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. Person.prototype = new Chinese(); //这里因为在prototype中使用了new,则会指向Chinese
  9. console.log(Person.prototype.constructor); //Chinese(){}
  10. Person.prototype.constructor = Person; //这里需要把constructor构造函数重新改为Person
  11. console.log(Person.prototype.constructor); //Person(){}
  12. var p1 = new Person("Oli", 18);
  13. console.log(p1.nationality); //Chinese

需要注意的是:在继承中,如果替换了prototype,那么新的prototype必须修改constructor属性,将这个属性指回到原来的构造函数。

利用空对象间接继承

</>复制代码

  1. function Chinese() {}
  2. Chinese.prototype.nationality = "Chinese";
  3. function Person(name, age) {
  4. this.name = name;
  5. this.age = age;
  6. }
  7. function F(){}; //空对象几乎不占用内存
  8. F.prototype = Chinese.prototype;
  9. Person.prototype = new F();
  10. Person.prototype.constructor = Person;
  11. Person.prototype.sayName = function() { //Person的prototype中的方法和属性需要在继承之后定义
  12. console.log(this.name);
  13. };
  14. var p1 = new Person("Oli", 18);
  15. console.log(p1.nationality); //Chinese
  16. p1.sayName(); //Oli

可以将该方法定义为函数:

</>复制代码

  1. function extend(Child, Parent) {
  2. var F = function() {};
  3. F.prototype = Parent.prototype;
  4. Child.prototype = new F();
  5. Child.prototype.constructor = Child;
  6. Child.uber = Parent.prototype; //用于访问父对象的prototype,可用可不用
  7. }

举例:

</>复制代码

  1. function extend(Child, Parent) {
  2. var F = function() {};
  3. F.prototype = Parent.prototype;
  4. Child.prototype = new F();
  5. Child.prototype.constructor = Child;
  6. Child.uber = Parent.prototype;
  7. }
  8. function Chinese() {}
  9. Chinese.prototype.nationality = "Chinese";
  10. function Person(name, age) {
  11. this.name = name;
  12. this.age = age;
  13. }
  14. extend(Person, Chinese);
  15. Person.prototype.sayName = function() {
  16. console.log(this.name);
  17. };
  18. var p1 = new Person("Oli", 18);
  19. console.log(p1.nationality); //Chinese
  20. p1.sayName(); //Oli

拷贝继承

使用下面的函数逐一将prototype的属性和函数拷贝到对象中:

</>复制代码

  1. function extend(Child, Parent) {    
  2. var p = Parent.prototype;    
  3. var c = Child.prototype;    
  4. for (var i in p) {      
  5. c[i] = p[i];      
  6. }    
  7. c.uber = p;  
  8. }

不需要先继承后定义

传统prototype模式继承(例子)

</>复制代码

  1. function Parent() {
  2. this.name = "thisIsName";
  3. }
  4. Parent.prototype.sayName = function() {
  5. return this.name;
  6. };
  7. function Child() {
  8. this.age = "thisIsAge";
  9. }
  10. Child.prototype = new Parent();
  11. Child.prototype.constructor = Child;
  12. Child.prototype.sayAge = function() {
  13. return this.age;
  14. };
  15. var c = new Child();
  16. console.log(c.name);
  17. console.log(c.age);
  18. console.log(c.sayName());
  19. console.log(c.sayAge());

call和apply与拷贝继承相配合(例子)

</>复制代码

  1. function extend(C, P) {
  2. var p = P.prototype;
  3. var c = C.prototype;
  4. for(var i in p){
  5. c[i] = p[i];
  6. }
  7. c.uber = p;
  8. }
  9. function Parent() {
  10. this.name = "thisIsName";
  11. }
  12. Parent.prototype.sayName = function() {
  13. return this.name;
  14. };
  15. function Child() {
  16. Parent.apply(this); //继承构造函数内的属性和方法
  17. this.age = "thisIsAge";
  18. }
  19. Child.prototype.sayAge = function() {
  20. return this.age;
  21. };
  22. extend(Child, Parent); //不需要先继承后定义
  23. var c = new Child();
  24. console.log(c.name);
  25. console.log(c.age);
  26. console.log(c.sayName());
  27. console.log(c.sayAge());

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79165.html

相关文章

  • 你是否理解js的Object与Function与原型链

    摘要:原型对象是由创建的,因此原型对象的构造函数是构造函数也可以是称为对象,原型对象也就继承了其生父构造函数中的数据,也同时继承了原型对象的数据。当然这条原型链中的数据,会被还是还是这类构造函数继承,但是不会被这些继承,他们不处于同一个链条上。 js中,Function的本质是什么?Object的本质又是什么?js中有几条原型链? showImg(https://segmentfault.c...

    itvincent 评论0 收藏0
  • js继承理解

    摘要:创建自定义的构造函数之后,其原型对象只会取得属性,其他方法都是从继承来的。优缺点寄生式继承在主要考虑对象而不是创建自定义类型和构造函数时,是十分有用的。 原文链接:https://kongchenglc.coding.me... 1.原型链   js的继承机制不同于传统的面向对象语言,采用原型链实现继承,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。理解原型链必须先理...

    BlackFlagBin 评论0 收藏0
  • JS中原型的理解

    摘要:我们都知道在的世界中,几乎所有东西都是对象,而对象又是通过继承来层层获得属性和方法,首先我们要区分对象和构造函数的区别,中对象继承的是对象,函数继承的是函数虽然函数也是对象,只有函数才有原型属性供它实例的对象继承,也就是说在中显示如下字符串 我们都知道在JS的世界中,几乎所有东西都是对象,而对象又是通过继承来层层获得属性和方法, var str = new String(mario);...

    fxp 评论0 收藏0
  • 面向对象的 JavaScript

    摘要:是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。而在基于原型的面向对象方式中,对象则是依靠构造器利用原型构造出来的。 JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或者只是部分具备一些面向对象的特征。本文将回归面向对象本意,从对语言感悟的角度阐述为什...

    novo 评论0 收藏0
  • js继承从入门到理解

    摘要:问题修改实例的,即修改了构造函数的原型对象的共享属性到此处,涉及到的内容大家可以再回头捋一遍,理解了就会觉得醍醐灌顶。 开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什么,prototype是什么,以及各种继承方法的优点和缺点,想必有好...

    不知名网友 评论0 收藏0
  • JavaScript之深入各种继承

    摘要:通常有这两种继承方式接口继承和实现继承。理解继承的工作是通过调用函数实现的,所以是寄生,将继承工作寄托给别人做,自己只是做增强工作。适用基于某个对象或某些信息来创建对象,而不考虑自定义类型和构造函数。 一、继承的概念 继承,是面向对象语言的一个重要概念。通常有这两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。 《JS高程》里提到:由于函数没有签名,...

    tomlingtm 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<