在 Es5 中没有类的概念, 在将类之前我们首先要说一下类的继承
类的继承
类有三种属性,, 公有属性, 私有属性, 静态属性 (Es7)/ 静态类 (Es6)
如何实现一个类
继承公有属性
- function Parent(){
- this.name = 'parent';
- }
- new Parent();//this 指向当前实例
- Parent() //this 指向 window
- function Child(){
- this.age = 9;
- Parent.call(this);// 相当于 this.name = 'parent' // 继承私有属性
- }
继承私有属性
- function Parent(){
- this.name = 'parent';
- }
- Parent.prototype.eat = function(){
- console.log('eat')
- }
- function Child(){
- this.age = 9;
- Parent.call(this);// 相当于 this.name = 'parent' // 继承私有属性
- }
- Child.prototype.smoking = function(){
- console.log('smoking')
- }
- Child.prototype = Parent.prototype;// 这个不叫继承
- // 因为这样如果改变 Child.prototype 加属性, Parent.prototype 的实例也会有这个属性,, 此时这两者属于兄弟关系
- Child.prototype._proto_ = Parent.prototype // 方法一
- //object.create
- Child.prototype = object.create(Parent.prototype); // 常用, 方法二
- function create(parentPrototype,props){
- function Fn(){}
- Fn.prototype = parentPrototype;
- let fn = new Fn();
- for(let key in props){
- Object.defineProperty(fn,key,{
- ...props[key],
- enumerable:true
- });
- }
- return fn();
- }
- Child.prototype = create(Parent.prototype,{constructor:{value:Child}})
- ![](https://user-gold-cdn.xitu.io/2018/5/28/163a486d1740a83f?w=1220&h=634&f=png&s=369712)
继承公有属性和私有属性
Child.prototype = new Parent()
类的编译
类只能 new
- class Parent{
- // 私有属性
- constructor(){
- this.name = 'parent',
- this.age = '40'
- }
- // 公有属性, 原型上的方法
- eat(){
- console.log('eat')
- }
- // 静态方法 / 属性 es6/es7
- // 属于类上的方法 Child.a()
- static b(){
- return 2
- }
- }
- new Parent();
- class Child extends Parent{ // 继承父亲的私有和公有
- // 私有属性
- constructor(){
- super() // 相当于 Parent.call(this)
- this.name = 'child'
- }
- // 公有属性, 原型上的方法
- smoking(){
- console.log('smoking')
- }
- // 静态方法 / 属性 es6/es7
- // 属于类上的方法 Child.a()
- static a(){
- return 1
- }
- }
- let child = new Child();
- console.log(child.name,child.age,child.eat(),child.smoking,Child.b())
- // 类可以继承公有, 私有和静态
- // 父类的构造函数中返回类一个引用类型, 会把这个引用类型作为子类的 this
我们首先写一个创建类的函数
- // 检测实例是不是 new 出来的
- function _classCallCheck(instance,constructor){
- if(!(instance instanceof constructor)){
- throw new Error('Class constructor Child cannot be invoked without new')
- }
- }
- //constructor 构造函数
- //prprotoPropertys 构造函数原型
- //staticPropertys 静态方法的描述
- function definePropertys(target,arr){
- for(let i=0;i<arr.length;i++){
- Object.defineProperty(target,arr[i].key,{
- ...arr[i],
- configurable : true,
- enumerable : true,
- writable:true
- })
- }
- }
- function _createClass(constructor,protoPropertys,staticPropertys){
- if(protoPropertys.length> 0){
- definePropertys(constructor.prototype,protoPropertys)
- }
- if(staticPropertys.length> 0){
- definePropertys(constructor,staticPropertys)
- }
- }
- let Parent = function(){
- // 写逻辑
- function P(){
- _classCallCheck(this,P)
- this.name = 'parent';
- //return {}
- }
- _createClass(P,// 属性描述器
- [
- {
- key: 'eat',
- value: function () {
- console.log('吃')
- }
- }
- ],
- [
- {
- key:'b',
- value:function () {
- return 2;
- }
- }
- ]
- )
- return P;
- }()
- let p = new Parent();
- console.log(p.eat())
上面这个函数没有继承作用, 下面我们逐步完善
类的继承
- function _inherits(subClass,superClass){
- // 继承公有属性
- subClass.prototype = Object.create(superClass.prototype,{constructor:{
- value:subClass
- }})
- // 继承静态方法
- Object.setPrototypeOf(subClass,superClass);
- }
- let Child = (function(Parent){
- _inherits(C,Parent)
- // 继承私有属性
- function C(){
- _classCallCheck(this,C);
- let that = this;
- let obj = Parent.call(this);// 继承并执行父类
- if(typeof obj === 'object'){
- that = obj
- }
- that.age = 9 ; // 解决了父类返回引用类型的问题
- }
- return C;
- })(Parent)
- let child = new Child()
- console.log(child)
- console.log(Child.b())
- console.log(parent)
- [Running] node "/Users/myloveyunyun/Desktop/node/pro.js"
- C { name: 'parent', age: 9 }
- 2
- P { name: 'parent' }
这样我们的类就创建完成了
来源: https://juejin.im/post/5b0abc85f265da0dbd7a648a