一、用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)
複製程式碼
好了,到這裡介紹完畢~~~ ???