JavaScript 继承 - ES6的class继承用ES5如何实现?
JavaScript 继承
前置知识
原型和原型链
- 在函数定义时,会自动会函数添加prototype属性,,默认是一个空Object对象,这个对象叫做原型对象。
- 实例对象的__proto__属性,叫做隐式原型属性/隐式原型,创建对象时自动添加的,对象的隐式原型的值=对应构造函数的显式原型的值
- 原型对象有一个constructor属性,指向函数对象
new 构造函数的原理
- 立刻创建一个新的对象
- 将该对象的__proto__指向构造器的prototype属性
- 将函数中的this设置成新建对象,在构造函数中可以使用this来引用新建的对象
- 逐行执行函数中的代码
- 将新建的对象作为返回值返回,如果构造返回的是对象,则返回对象
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; } }
- 子类构造函数(Child)的隐式原型__proto__ 指向父类构造器(Parent),继承父类的静态方法
- 子类实例的显式原型对象(Child.prototype)的隐式原型__proto__指向父类的显式对象(Parent.prototype),继承父类的方法
- 子类构造函数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; }
上一篇:
Java基础知识总结(2021版)