继承 JavaScript 有六种常见方法

小夏 文化 更新 2024-02-16

面向对象编程最重要的方面之一是对象的继承。 通过继承对象 B,对象 A 直接拥有对象 B 的所有属性和方法。这对于重用非常有用。

大多数面向对象的编程语言都使用类来实现对象继承。 传统上,j**ascript 语言中的继承不是通过类实现的(ES6 引入了类语法),而是通过“原型”来实现的。 那么JS中常见的继承方法有多少呢?

这种方法的关键是:子类型的原型是父类型的实例对象。

父类型 函数 人(姓名、年龄) 人prototype.setage = 函数 () 子类型 函数 student(price) studentprototype = new person() 子类型的原型是父类型的实例对象,var s1 = new student(15000),var s2 = new student(14000) consolelog(s1,s2)
但这种方法的本质是将子类的原型指向父类的实例,因此然后,学生可以访问子类的实例prototype 也是 person 的一个实例,这样就可以访问父类的私有方法,然后通过 proto 指向父类的原型,获取父类原型上的方法。因此,父类的私有和公共方法和属性被视为子类的公共属性。

子类继承父类的属性和方法,并将父类的私有属性和公共方法视为自己的公共属性和方法如果父类的私有属性中有引用类型属性,那么当它被子类继承时,它将被用作公共属性,因此当子类 1 操作该属性时,它将影响子类 2。

s1.play.push(4)console.log(s1.play, s2.play)console.log(s1.__proto__ === s2.__proto__)=== s2.__proto__.proto__)//true
play 属性在 S1 中发生了变化,play 属性在 S2 中也发生了变化。

另一件需要注意的事情是,当我们需要向子类添加新方法或重写父类中的方法时,请务必将其放在替换原型的语句之后

function person (name, age) person.prototype.setage = function ()function student (price) }// student.prototype.sayhello = function() 在这里写原型方法和子类的属性是无效的,因为它会改变原型的方向,所以应该放在重新命名之后prototype = new person()student.prototype.sayhello = function ()var s1 = new student(15000)console.log(s1)
特征:

父类的新原型方法 prototype 属性对于所有子类都很简单且易于实现缺点:

不可能实现所有实例共享的原型对象的所有属性的多个继承在创建子类实例时,无法将参数传递给父类构造函数为了向子类添加属性和方法,必须使用student.prototype = new person()之后,不将其放入构造函数的关键如下:在子类型构造函数中,泛型 call() 调用父类型构造函数

function person(name, age) person.prototype.setage = function ()function student(name, age, price) var s1 = new student('tom', 20, 15000)
这种方法只实现部分继承,如果父类原型也有方法和属性,则子类将无法获取它们。

console.log(s1.setage())//uncaught typeerror: s1.setage is not a function
特征:

解决了原型链继承中子类实例共享父类引用属性的问题,在创建子类实例时,可以将参数传递给父类,并实现多重继承(调用多个父类对象)缺点:

实例不是父类的实例,但子类的实例只能继承父类的实例属性和方法,不能继承原型的属性和方法来实现函数复用通过调用父类构造,继承父类的属性并保留传递参数的优点,然后使用父类实例作为子类原型,该函数被重用。

function person (name, age) }person.prototype.setage = function ()function student (name, age, price) }student.prototype = new person()student.prototype.constructor = 学生 组合继承也是学生。 构造函数指向的需要修复prototype.sayhello = function ()var s1 = new student('tom', 20, 15000)var s2 = new student('jack', 22, 14000)console.log(s1)console.log(s1.constructor) //person
这种方法结合了原型链继承和构造函数的优点,是 j**ascript 中最常用的继承模式。 缺点是构造函数在任何情况下都会被调用两次:一次是在创建子类型的原型时,一次是在子类型构造函数中,该构造函数最终包含父对象的所有实例属性,但是在调用子类构造函数时,我们必须覆盖这些属性。

优点:

可以继承实例属性方法,也可以继承原型属性方法,不存在引用属性共享问题,参数函数可以复用缺点:

父构造函数被调用了两次,导致两个实例这样,父类原型和子类原型指向同一个对象,子类可以作为自己的公共方法继承到父类的公共方法,并且不初始化两次实例方法属性,避免了组合继承的缺点

function person (name, age) }person.prototype.setage = function ()function student (name, age, price) }student.prototype = person.prototypestudent.prototype.sayhello = function ()var s1 = new student('tom', 20, 15000)console.log(s1)
但是,无法判断对象是子实例化还是父实例化。

console.log(s1 instanceof student, s1 instanceof person)//true trueconsole.log(s1.constructor)//person
优点:

双实例方法属性不初始化,避免了组合继承的弊端缺点:

无法判断实例是由子类还是父类创建的,并且子类和父类的构造函数指向相同的实例。 原型允许您根据已有的对象创建对象var b = object.create(a)基于对象 A,生成对象 B。 B 继承了 A 的所有属性和方法。

function person (name, age) person.prototype.setage = function ()function student (name, age, price) }student.prototype = object.create(person.原型)核心**学生prototype.constructor = Student core**var s1 = new student('tom', 20, 15000)console.log(s1 instanceof student, s1 instanceof person) // true trueconsole.log(s1.constructor)
同样,学生继承 Person 原型对象的所有属性和方法。 至此,完美的传承方法!

ES6 引入了 class 关键字,可以通过 extends 关键字继承,也可以通过 static 关键字定义类的静态方法,这比通过修改原型链来实现继承的 ES5 更清晰、更方便。

ES5 中的继承本质上是创建一个子类 this 的实例对象,然后在 this(parent.)之上添加父类的方法。apply(this))。ES6 有一个完全不同的继承机制,本质上是将父类实例对象的属性和方法添加到这个对象中(所以你必须先调用 super 方法),然后用子类的构造函数修改它。

需要注意的是,class 关键字只是原型的句法糖,j**ascript 继承还是基于原型的

class person 定义通用方法 showname()let p1 = new person('kobe', 39)console.log(p1) 定义了一个子类: class student extends person showname () let s1 = new student('wade', 38, 1000000000)console.log(s1)s1.showname()
优点:

语法简单易懂,操作更方便缺点:

不是所有的浏览器都支持 class 关键字js 几种实现继承的方法j**ascript 多种方式和深度继承的优缺点j**ascript 常用继承方法阮一峰 es6 入门类继承方法 5:组合继承优化 2 我觉得也可以这样写:

function person (name, age) person.prototype.sayname = function() function student (name, age, price) student.prototype = object.create(person.prototype);student.prototype.constructor = student;这里将 sayage 原型方法放在继承语句之后,以防止 s1sayage() 错误,详见方法二:借用构造函数继承 studentprototype.sayage = function() var p1 = new person('join', 30);var s1 = new student('tom', 20, 1500);console.log(p1.sayname())// joinconsole.log(s1.sayage())// 20

相似文章

    六种常见的自家种植蔬菜

    在现代都市生活中,越来越多的人开始注重健康饮食,尝试在家种菜。自家种植的蔬菜不仅可以享受新鲜的有机食材,还可以锻炼身心,培养情绪。下面我将介绍六种常见的自家种植的蔬菜。绿色蔬菜 绿色蔬菜是最常见的自家种植蔬菜之一。它易于生长,耐寒耐旱,生长迅速。一般来说,绿色植物在阳光充足 通风良好的地方种植效果最...

    假紫陶罐的六种常见类型

    在紫砂锅市场中,常见的假紫砂锅有六种,需要消费者特别注意。这些假冒的紫砂锅不仅欺骗了消费者的感情,还可能对消费者的健康造成潜在的危害。首先,灌浆锅是用石膏模具制成的,并浇注泥浆。由于生产工艺简单,价格低廉,这种锅在市场上很常见。它的特点是身体非常薄,颜色通常较深。但由于灌浆锅生产过程缺乏严谨性,很难...

    这六种简单常用的方法,足以让你的女朋友开心

    在一段关系中,关注对方的情绪,及时采取行动,表达自己的心声是必不可少的。对于一个男孩来说,当女朋友心情不好或者惹女朋友生气时,他怎么能让她开心呢?其实,让女朋友开心并不难,关键是要了解她的需求和心情,用正确的方法去安慰她。无论是送一份小礼物 一束鲜花 写一封情书,还是做一顿丰盛的饭菜,都让她感受到你...

    您使用过六种常见的旋风除尘器中的哪一种?

    旋风除尘器是一种利用旋风分离器原理,通过高速旋转的气流将粉尘从空气中分离出来的设备。市场上常见的旋风分离器有六种,它们是 .多管旋风除尘器 该除尘器由多个并联的小型旋风分离器组成,能够处理大风量 中等浓度的粉尘。多管旋风除尘器除尘效率高,适用于工业炉 水泥厂等场所。.卧式旋风除尘器 该除尘器采用卧式...

    用六种常见成分的组合来摆脱恼人的痤疮,以帮助您实现它!

    导语 随着饮食的改变,痤疮已经成为越来越多人的难题。然而,只要你吃正确的食材,你就可以轻松摆脱烦人的痤疮。.西红柿配黄瓜。西红柿含有抗氧化剂,而黄瓜则为身体补充所需的水分。两者的结合在治疗易长粉刺的皮肤方面非常有效。.海带鸡蛋。鸡蛋含有胶原蛋白,而海带富含碘和海藻酸,可有效舒缓痘痘,使皮肤更有弹性。...