js中对象继承的方式

文章类型:Javascript

发布者:hp

发布时间:2023-04-08

一:以原型链的方式,将父类的实例作为子类的原型

1:包含有引用类型的数据时,会被所有的实例对象所共享,容易造成修改的混乱。

2:创建子类型的时候不能向超类型传递参数。

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

function Child() {
  this.age = 10;
}

Child.prototype = new Parent();

var child = new Child();
console.log(child.name); // 输出 "Parent"

二:使用借用构造函数的方式,使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类

1:无法实现函数方法的复用,并且超类型原型定义的方法子类型也没有办法访问到

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

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

var child = new Child();
console.log(child.name); // 输出 "Parent"

三:组合继承,将原型链和借用构造函数组合

1:将原型链和借用构造函数组合起来。

2:通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承。

3:解决了上面的两种模式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。

function Parent(value) {
		this.val = value
	  }
	  Parent.prototype.getValue = function() {
		console.log(this.val)
	  }
	  function Child(value) {
		Parent.call(this, value)
	  }
	  Child.prototype = new Parent()

	  const child = new Child(1)

	  child.getValue() // 1
	  child instanceof Parent // true

四:原型式继承

1:基于已有的对象来创建新的对象,

2:向函数中传入一个对象,然后返回一个以这个对象为原型的对象。

3:主要不是为了实现创造一种新的类型,只是对某个对象实现一种简单继承。

var parent = {
  name: 'Parent',
  sayHello: function() {
    console.log('Hello, ' + this.name);
  }
};

var child = Object.create(parent);
child.name = 'Child';
child.sayHello(); // 输出 "Hello, Child"

五:寄生式继承

1:创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,然后对象进行扩展,最后返回这个对象。

2::扩展的过程就可以理解是一种继承。

3:优点就是对一个简单对象实现继承,如果这个对象不是自定义类型时。缺点是没有办法实现函数的复用。

function Parent(value) {
		this.val = value
	  }
	  Parent.prototype.getValue = function() {
		console.log(this.val)
	  }

	  function Child(value) {
		Parent.call(this, value)
	  }
	  Child.prototype = Object.create(Parent.prototype, {
		constructor: {
		  value: Child,
		  enumerable: false,
		  writable: true,
		  configurable: true
		}
	  })

	  const child = new Child(1)

	  child.getValue() // 1
	  child instanceof Parent // true

六:寄生式组合继承

1:使用超类型的实例做为子类型的原型,导致添加了不必要的原型属性。

2:使用超类型的原型的副本来作为子类型的原型,这样就避免了创建不必要的属性。

function inheritPrototype(subType, superType) {
  // 创建父类原型的副本
  var prototype = Object.create(superType.prototype);
  // 将副本的构造函数设置为子类构造函数
  prototype.constructor = subType;
  // 将副本设置为子类的原型
  subType.prototype = prototype;
}

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

Parent.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};

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

// 使用寄生式组合继承
inheritPrototype(Child, Parent);

Child.prototype.sayAge = function() {
  console.log('I am ' + this.age + ' years old');
};

var child = new Child('Alice', 10);
child.sayHello(); // 输出 "Hello, Alice"
child.sayAge(); // 输出 "I am 10 years old"
console.log(child instanceof Parent); // 输出 true
console.log(child instanceof Child); // 输出 true

七:es6中的类继承

1:使用引入的class关键字和extends关键字来定义类和实现继承

2:使用super关键字调用父类的构造函数

class Parent {
  constructor(name) {
    this.name = name;
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
}

const child = new Child('Child', 10);
console.log(child.name); // 输出 "Child"
console.log(child.age); // 输出 10