Babel 一下 ES6 中的類及繼承

風辰月發表於2018-07-13

一、用ES5實現繼承

1、建立父類

function Father () {
  // 私有屬性
  this.name = 'father'
  // 私有方法
  this.eat = function () {
    console.log('eat')
  }
}
// 公有方法
Father.prototype.sleep = function () {
  console.log('sleep')
}

Father() // 此時控制檯輸出掛載在window物件上的方法,可知沒有建立例項時this指向window

let father = new Father()
father.eat() // eat
father.sleep() // sleep
console.log(father) // Father { name: 'father', eat: [Function] }
複製程式碼

2、建立子類並繼承

function Child () {
  // 繼承父類的私有屬性和方法
  Father.call(this)
  // 自己的私有屬性
  this.name = 'child'
  // 自己的私有方法
  this.smoke = function () {
    console.log('smoke')
  }
}
// 繼承父類的公共方法:將Child的prototype指向Father的prototype,同時修改Child.prototype.constructor為Child本身
Child.prototype = Object.create(Father.prototype, { constructor: { 
  value: Child,
  enumerable: false,
  writable: true,
  configurable: true
}})
// 修改原型鏈:將Child的原型鏈指向所從屬的原型上,即Child.__proto__ = Father,或者
Object.setPrototypeOf(Child, Father)

let child = new Child()
child.eat() // eat
child.sleep() // sleep
child.smoke() // smoke
console.log(Child.__proto__.prototype === Father.prototype) // true
複製程式碼

二、用es6實現繼承

class Father {
  constructor () {
    // 私有屬性
    this.name = 'father'
  }
  // 公有方法
  eat () {
    console.log('eat')
  }
  // 靜態方法,可直接訪問的私有方法
  static sleep () {
    console.log('sleep')
  }
}

class Child extends Father {
  constructor() {
    super()
    // 私有屬性
    this.name = 'child'
    this.age = 12
  }
  // 公有方法
  smoke () {
    console.log('smoke')
  }
}

let child = new Child()
child.eat() // eat
Child.sleep() // sleep
child.smoke() // smoke
複製程式碼

三、手動實現ES6中類及繼承

1、實現父類

// 因為類例項需要new建立,不能直接使用,所以需要一個類呼叫檢查函式,即_classCallCheck函式
function _classCallCheck (instance, Constructor) {
  if (!instance instanceof constructor) {
    throw new TypeError('cannot call a class as a function')
  }
}
// 類建立函式: Constructor是原型 protoProps是公有方法 staticProps是靜態方法,也是私有方法
function _createClass(Constructor, protoProps, staticProps) {
  function defineProperties(target, props) {
    for (let i = 0; i < props.length; i++) {
      Object.defineProperty(target, props[i].key, {
        value: props[i].value,
        enumerable: true,
        writable: true,
        configurable: true
      })
    }
  }
  // 新增公有方法
  if (protoProps) {
    defineProperties(Constructor.prototype, protoProps)
  }
  // 新增靜態方法,也是私有方法
  if (staticProps) {
    defineProperties(Constructor, staticProps)
  }
  return Constructor
}
let Father = function () {
  function Father () {
    // 類呼叫檢查
    _classCallCheck(this, Father)
    // 私有屬性
    this.name = 'father'
    // return {
    //   hobby: 'basketball'
    // }
  }
  // 下面是實現類,即把公有方法繫結到Father的prototype上,靜態方法直接放到Father上
  _createClass(Father,[
    {
      key: 'eat',
      value: function eat () {
        console.log('eat')
      }
    }
  ],
  [
    {
      key: 'sleep',
      value: function sleep () {
        console.log('sleep')
      }
    }
  ])
  return Father
}()
複製程式碼

2、實現子類及繼承

// 函式作用:繼承父類的公共方法和修改原型鏈
function _inherits(subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError('super expression must either be null or a function,not' + typeof superClass)
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  })
  if (subClass) {
    Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass
  }
}
let Child = function (Father) {
  // 繼承父類的公有方法:將Child的prototype指向Father的prototype,同時修改Child.prototype.constructor為Child本身
  // 修改原型鏈:將Child的原型鏈指向所從屬的原型上,即Child.__proto__ = Father
  _inherits(Child, Father)

  function Child () {
    // 類呼叫檢查
    _classCallCheck(this, Child)
    // 繼承私有屬性
    let obj = Father.call(this)
    // 這裡是因為父類函式可以返回一個新物件(見父類註釋)
    let that = this
    if (typeof obj === 'object') {
      that = obj
    }
    that.name = 'Child'
    that.age = 12
    return that
  }
  _createClass(Child, [{
    key: 'smoking',
    value: function smoking() {
      console.log('smoking')
    }
  }])
  return Child
}(Father)
複製程式碼

好了,到這裡介紹完畢~~~ ???

相關文章