JavaScript 继承 - ES6的class继承用ES5如何实现?

JavaScript 继承

前置知识

原型和原型链

  1. 在函数定义时,会自动会函数添加prototype属性,,默认是一个空Object对象,这个对象叫做原型对象。
  2. 实例对象的__proto__属性,叫做隐式原型属性/隐式原型,创建对象时自动添加的,对象的隐式原型的值=对应构造函数的显式原型的值
  3. 原型对象有一个constructor属性,指向函数对象

new 构造函数的原理

  1. 立刻创建一个新的对象
  2. 将该对象的__proto__指向构造器的prototype属性
  3. 将函数中的this设置成新建对象,在构造函数中可以使用this来引用新建的对象
  4. 逐行执行函数中的代码
  5. 将新建的对象作为返回值返回,如果构造返回的是对象,则返回对象
function myNew(Fn,...args){
          
   
  let obj = {
          
   }; //1.定义空对象
  //1.获取构造函数,将该对象的__proto__指向构造器的prototype属性
  obj.__proto__ = Fn.prototype;
 //2.将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
 //3.逐行执行函数中的代码,如果有返回值记录返回值
  let res = Fn.apply(obj,args);
  return res instanceof Object ? res : obj;//4.如果有返回值直接返回且为对象直接返回,如果没有则返回新建的对象
}

ES6的Class类

class可以看作只是一个语法糖,只是让对象原型的写法更加清晰,更像面向对象编程的语言。 class是构造函数的另外一种写法。

类的所有方法都定义在类的prototype属性上面。

class Person{
          
   
 constructor(){
          
   }
}

console.log(typeof Person);//function
console.log(Person===Person.prototype.constructor);//true

class Cat {
          
       
constructor() {
          
   }    
hideTheShit () {
          
   }
}
// 等同于
function Cat () {
          
   }
Cat.prototype = {
          
   
    constructor() {
          
   }    
    hideTheShit () {
          
   }
}

继承 extends的作用

继承对于JS来说就是父类拥有的方法和属性、静态方法等,子类也要拥有。

class Parent{
          
   
    constructor(name){
          
   
        this.name = name;
    }
}
class Child extends Parent{
          
   
    constructor(name, age){
          
   
        super(name);
        this.age = age;
    }
}
  1. 子类构造函数(Child)的隐式原型__proto__ 指向父类构造器(Parent),继承父类的静态方法
  2. 子类实例的显式原型对象(Child.prototype)的隐式原型__proto__指向父类的显式对象(Parent.prototype),继承父类的方法
  3. 子类构造函数Child父类构造函数Parent的里的属性,使用super调用的。子类构造器里调用父类构造器,继承父类的属性。
// 1.构造器原型链
Child.__proto__ === Parent; // true
// 2.实例原型链
child.__proto__ === Child.prototype; // true

寄生组合式继承

根据extends作用可以推出继承的写法,首先是需要改变__proto__指向。

    new Object.create(proto,[propertiesObject]) ES5 方法创建一个新对象,创建对象的__proto__指向第一个参数。 Object.setPrototypeOf(对象a,对象b) ES6 方法设置对象a的__proto__指向对象b
function Parent(name){
          
   
	this.name = name;
}
function Child(name,age){
          
   
	//相当于super
	Parent.call(this,name);
	this.age = age;
}
//继承
function inherits(Child,Parent){
          
   
	//子类可以看见父类的方法
	 Child.prototype = Object.create(Parent.prototype);
	//Child.prototype.__proto__  = Parant.prototype;
	//Object.create创建的是一个新对象,所以需要显式指定constructor属性
	Child.prototype.constructor = Child;
	//子类可以看见父类的静态方法
	//Object.setPrototypeOf(Child,Parent); ES6
	Child.__proto__ = Parant;	
}
经验分享 程序员 微信小程序 职场和发展