【笔记】JS实现继承的几种方式

文章介绍了JavaScript中实现继承的多种方式,包括原型链继承、借用构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承以及ES6的class和extends关键字的使用。每种方式都有其特点和适用场景,如原型链继承不能传参,组合继承可能调用两次构造函数,而ES6的class语法更简洁但需注意super的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在JavaScript中,有多种方式可以实现继承。以下是常见的几种继承方式:

1. 原型链继承

原型链继承是指将父类实例作为子类的原型。这种方式下,子类实例可以共享父类实例的属性和方法,但是无法向父类构造函数传递参数。

 function Parent() {
	this.name = 'parent';
 }

 Parent.prototype.sayHello = function() {
	console.log('hello from parent');
 }

 function Child() {}

 Child.prototype = new Parent();

 var child = new Child();
 child.sayHello(); // hello from parent

2. 借用构造函数继承

借用构造函数继承是指在子类构造函数中调用父类构造函数,并使用 call 或 apply 方法将父类的 this 指向子类实例。这种方式的缺点是无法继承父类原型上的方法。

 function Parent(name) {
 	this.name = name;
 }

 Parent.prototype.say = function() {
	 console.log('父亲说:你要听话。')
 }

 function Child(name, age) {
 	Parent.call(this, name);
 	this.age = age;
 }

 const child = new Child('小红', 18);
 console.log(child.name); // 小红
 console.log(child.age); // 18
 child.say() // 报错 child.say is not a function

3. 组合继承

组合继承是指将原型链继承和借用构造函数继承结合起来。这种方式可以继承父类实例和原型上的属性和方法,但是会调用两次父类构造函数,且父类原型上的属性和方法会被继承两次。

 function Parent(name) {
	 this.name = name;
 }

 Parent.prototype.sayHello = function() {
	 console.log('hello from parent');
 }

 function Child(name, age) {
	 Parent.call(this, name);
	 this.age = age;
 }

 Child.prototype = new Parent();
 Child.prototype.constructor = Child;

 const child = new Child('小红', 18);
 console.log(child.name); // child
 console.log(child.age); // 18
 child.sayHello(); // hello from parent

4. 原型式继承

原型式继承是指创建一个空对象,并将父类实例作为该空对象的原型。这种方式的缺点与原型链继承相同。

 function createObject(obj) {
	 function F() {}
	 F.prototype = obj;
	 return new F();
 }

 const parent = {
 	 name: 'parent',
 	 sayHello: function() {
     	 console.log('hello from parent');
     }
 };

 const child = createObject(parent);
 console.log(child.name); // parent
 child.sayHello(); // hello from parent

5. 寄生式继承

寄生式继承是指创建一个新对象,并在该对象上增加一些父类的属性和方法,然后返回该对象。这种方式的缺点与原型式继承相同。

 function createObject(obj) {
	 const o = Object.create(obj);
	 o.sayHello = function() {
	 	 console.log('hello from child');
	 };
	 return o;
 }

 const parent = {
	 name: 'parent'
 }

 const child = createObject(parent);
 console.log(child.name); // parent
 child.sayHello(); // hello from child

6. 寄生组合式继承

寄生组合式继承是指使用“借用构造函数”继承父类实例的属性和方法,并将子类原型指向一个父类实例的副本。这种方式可以避免调用两次父类构造函数,且不会继承父类原型上的属性和方法。

 function Parent(name) {
 	 this.name = name;
 }

 Parent.prototype.sayHello = function() {
	 console.log('hello from parent');
 };

 function Child(name, age) {
	 Parent.call(this, name);
	 this.age = age;
 }

 Child.prototype = Object.create(Parent.prototype);
 Child.prototype.constructor = Child;

 const child = new Child('小红', 18);
 console.log(child.name); // 小红
 console.log(child.age); // 18
 child.sayHello(); // hello from parent

7. ES6 中,可以使用 class 和 extends 关键字来实现继承。即定一个父类(也称为基类)和一个子类(也称为派生类),并通过 extends 关键字让子类继承父类的属性和方法。

 class Parent {
	 constructor(name) {
		 this.name = name;
     }
     sleep() {
		 console.log(`${this.name} 在睡觉`);
	 }
 }

 class Child extends Parent {
	 constructor(name) {
 		 super(name);
     }
     
     // 子类定义了一个新方法
     play() {
     		console.log('玩耍');
     }

     // 子类重写父类的 sleep 方法
     sleep() {
          super.sleep();
          console.log('睡觉');
	 }
 } 

 const child = new Child('小红');
 console.log(child.name); // 小红
 child.play(); // 玩耍
 child.sleep(); //  依次输出 “小红在睡觉” 和 “睡觉”

需要注意的是:子类中的构造函数必须调用 super 方法,以便初始化父类的属性。同时,父类中定义在构造函数中的属性和方法,并不会被自动继承到子类中,需要通过 super 关键字来获取这些属性和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值