JS面向對象

類與實例

建立類

//es6
class Animal1 {
  constructor () {
    this.name = name
  }
}
//es5
function Animal2 (name) {
  this.name = name
}
複製代碼

實例化

let new1 = new Animal1()
let new2 = new Animal2()
複製代碼

類與繼承

實現繼承的幾種方式

  • 方式一:利用構造函數進行繼承
function Parent1 () {
  this.name = '父'
 }
function child1 () {
  Parent1.call(this) //重點 將父級構造的this指向指到子類的實例上去,父類的屬性子類也會有
  this.type = 'child'
 }
console.log(new child1)
複製代碼

可是這種方法缺點是沒法繼承父類的原型鏈上的屬性es6

  • 方式二: 利用原型鏈進行繼承
function Parent2 () {
  this.name = 'parent2'
  this.arr = [1, 2, 3]
}
function child2 () {
   this.type = 'child2'
}
child2.prototype = new Parent2()
console.log(new child2)
let s1 = new child2()
let s2 = new child2()
s1.arr.push(4)
console.log(s1.arr, s2.arr)  //輸出都是 [1, 2, 3, 4]
複製代碼

這樣能繼承原型鏈上的屬性,可是若是改變父類的元素,全部的子類屬性也會進行更改,由於這至關於改變了原型對象bash

  • 方式三: 組合方法,同時使用構造函數跟原型鏈
function parent3 () {
   this.name = 'parent3'
   this.arr = [1, 2 ,3]
}
function child3 () {
    parent3.call(this)  //執行一次父類
    this.type = 'child3'
}
 child3.prototype = new parent3() // 再次執行父類
 let s3 = new child3()
 let s4 = new child3()
 s3.arr.push(4)
 console.log(s3, s4) // [1,2,3,4] [1,2,3]
複製代碼

可是這種方法也不是完美的,這種方法還有個弊端就是父類被執行了兩次函數

  • 方式三 優化1
function parent4 () {
  this.name = 'parent4'
  this.arr = [1, 2 ,3]
}
function child4 () {
  parent3.call(this)
  this.type = 'child4'
}
child4.prototype = parent4.prototype 
複製代碼

這樣就避免了父類被執行兩次,可是這還不算完美的,由於這樣沒法去區分實例是父類仍是子類直接建立的優化

  • 最終完美優化版
function parent5 () {
  this.name = 'parent5'
  this.arr = [1, 2 ,3]
}
function child5 () {
  parent3.call(this)
  this.type = 'child5'
}
// Object.create建立一箇中間對象,引用父類的原型對象,這樣用於隔離子類的原型對象跟父類的原型對象直接關聯
child5.prototype = Object.create(parent5.prototype)
//爲子類添加一個構造函數
child5.prototype.constructor = child5
console.log(child5.prototype.constructor === parent5.prototype.constructor)
//輸出false
複製代碼
相關文章
相關標籤/搜索