ES5中如何实现继承

目录

前言

ES5中的几种继承方式

1、原型链继承

2、借用构造函数继承

3、组合继承

4、寄生式组合继承


 

前言

了解JS继承之前,我们先来了解一下两个概念:

原型: 在JavaScript高级程序设计中给出的解释是· 每一个构造函数(对应的就是类函数)都有一个prototype属性(强调下是属性),这个prototype属性会指向一个原型对象(强调下是对象)。该原型属性指向的原型对象称之为原型。

原型链: 每一个构造函数的原型属性会链式指向原型对象,每个原型对象都会有个constructor属性会指向构造函数(未定义时默认指向构造函数)其中形成了一种链式结构,我们称之为原型链。

ES5中的几种继承方式

1、原型链继承

原型链继承的原理是直接让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承。

//父类
function Parents(){
  this.name = '张三';
  this.play = [1,2,3];
}
//子类
function Child(){

}
//让子类的原型对象指向父类实例, 这样一来在Child实例中找不到的属性和方法就会到原型对象(父类实例)上寻找
Child.prototype = new Parents();

var s1 = new Child();
var s2 = new Child();
console.log(s1.name,s2.name);
console.log(s1.play,s2.play);
//push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度
s1.play.push(4);
console.log(s1.play,s2.play);

  

缺点:

  • 由于所有Child实例原型都指向同一个Parent实例, 因此对某个Child实例的父类引用类型变量修改会影响所有的Child实例
  • 在创建子类实例时无法向父类构造传参, 即没有实现super()的功能

2、借用构造函数继承

构造函数继承,即在子类的构造函数中执行父类的构造函数,并为其绑定子类的this,让父类的构造函数把成员属性和方法都挂到子类的this上去,这样既能避免实例之间共享一个原型实例,又能向父类构造方法传参。

//父类
function Parent(){
  this.name = '张三';
}
//构造函数继承法:父类原型链上的属性和方法是无法继承的
Parent.prototype.getName = function() {
  return this.name
}
function Child(){
  Parent.call(this);//call()方法,apply()方法都可实现
}
let s3 = new  Child();
console.log(s3.name);
// s3.getName();/*找不到,会报错 */

缺点:

无法继承父类原型链上的属性和方法。

3、组合继承

组合上述两种 

function Parent(name) {
  this.name = [name]
}
Parent.prototype.getName = function() {
  return this.name;
}
function Child() {
  // 构造函数继承
  Parent.call(this, '张三') 
}
//原型链继承
Child.prototype = new Parent()
Child.prototype.constructor = Child;


let child1 = new Child()
let child2 = new Child()
child1.name[0] = 'hello'
console.log(child1.name)          // ['hello']
console.log(child2.name)          // ['张三']
child2.getName()                  // ['张三']
console.log(child2.getName());

缺点:

  • 每次创建子类实例都执行了两次构造函数(Parent.call()new Parent()),虽然这并不影响对父类的继承,但子类创建实例时,原型中会存在两份相同的属性和方法。

4、寄生式组合继承

解决构造函数被执行两次的问题, 我们将指向父类实例改为指向父类原型, 减去一次构造函数的执行。

function Parent(name) {
  this.name = [name]
}
Parent.prototype.getName = function() {
  return this.name
}
function Child() {
  // 构造函数继承
  Parent.call(this, '张三') 
}
//原型链继承
// Child.prototype = new Parent()
Child.prototype = Object.create(Parent.prototype)  //将`指向父类实例`改为`指向父类原型`
Child.prototype.constructor = Child

//测试
let child = new Child()
let parent = new Parent()
console.log(child.getName());    // ['张三']
console.log(parent.getName());  // 报错, 找不到getName()

 

这是目前较优的继承方式, 

你可能感兴趣的:(javascript,原型模式,javascript,前端)