JS OOP (面向?qū)ο缶幊蹋?/h2>

類 Class

1.通過一系列特性、行為對事物的特征進(jìn)行描述。
2.在類定義中,通過 屬性(數(shù)據(jù))描述事物的特性,通過 方法(操作)描述事物的 行為。

const Animal= function(name, type) {
  /* private members */
  var type = type                                                                // 私有屬性
  var isAnimal = function() { return type === 'animal' }      // 私有方法

  /* protect members */
  this.color = 'blue'
  Object.defineProperty(this, 'color', {
    get: function(){ if (this instanceof Animal) return color },
    set: function(v){ if (this instanceof Animal) color = v }
  })

  /* public members */ 
  this.name = name                                                           // 實(shí)例屬性
  this.animalName = function(){                                         // 實(shí)例方法
    // 實(shí)例方法可訪問私有屬性和方法,原型方法不可以
    isAnimal() && console.log(this.name)
  }
}
Animal.prototype = {
  constructor: Animal,
  type: ' animal ',                                                                 // 原型屬性
  action: function() { console.log(' eating, drinking ') }         // 原型方法
}
Animal.number = 0                                                             // 類靜態(tài)屬性
Animal.count = function(){ return Animal.number }            // 類靜態(tài)方法


抽象 Abstract

1.沒有足夠信息描述一個(gè)具體的事物,而僅對事物進(jìn)行概括性的描述。
2.無法展現(xiàn)出事物對象,必須要有事物的完整描述才能展現(xiàn)出對象。
3.抽象出的類 就像一張藍(lán)圖,只是告訴我們寶藏的位置,但想得到寶藏就必須我們自己去尋寶。

const Animal = function() { 
  this.initialize()                                           // 抽象類不可實(shí)例化,在校驗(yàn)抽象方法時(shí)異常
}
Animal.prototype.initialize = function() {
    this.walk()                                               // 抽象方法在初始化時(shí)進(jìn)行校驗(yàn)是否被派生類所實(shí)現(xiàn)
    this.yell()
  }
}


繼承 Inheritance

1.若多個(gè)事物具有很多相似的特性和行為,可以通過對基礎(chǔ)的描述進(jìn)行擴(kuò)充,而不需要重新描述。
2.派生出的類 就像繼承者,它不但獲得被繼承者的所有財(cái)產(chǎn),而且也擁有自己的財(cái)產(chǎn)。

  1. 原型鏈繼承(實(shí)例化時(shí)無法向父類構(gòu)造函數(shù)傳參、原型對象的引用 屬性 被所有實(shí)例共享)
function Cat(name, type) { this.type = type }          // 無法向父類傳遞name屬性
Cat.prototype = new Animal()                                // 原型指向?qū)ο蟊凰袑?shí)例共享
Cat.prototype.name = name                                  // 實(shí)例化后方可為父類初始化屬性值
  1. 構(gòu)造繼承(無法繼承原型的屬性和方法,每個(gè)子類均包含父類方法的副本)
function Cat(name, type) {
  Animal.call(this, name)                                       // 通過父類的構(gòu)造函數(shù)對子類實(shí)例對象進(jìn)行初始化
  Animal.prototype.contructor.call(this, name)      // 可多繼承 (原型的方法不會被直接繼承)
  this.type = type                                                   // 子類構(gòu)造函數(shù)初始化對象屬性(覆蓋父類)
  this.yell = function() { console.log('喵') }             // 子類構(gòu)造函數(shù)初始化對象方法(覆蓋父類)
}
  1. 實(shí)例繼承(擴(kuò)展后的父類實(shí)例,不支持多繼承)
function Cat(name, type) {
  var surperClass = new Animal(name)
  surperClass.type = type
  return surperClass
}
  1. 拷貝繼承(內(nèi)存占用高,無法獲取父類不可枚舉的屬性和方法)
function Cat(name) {
  var animal = new Animal()
  for(var p in animal) { Cat.prototype[p] = animal[p] }
  Cat.prototype.name = name
}
  1. 組合繼承(即可繼承實(shí)例屬性和方法,也可繼承原型屬性和方法)
function Cat(name, type) {
  Animal.call(this, name)      // 繼承父類實(shí)例的屬性和方法,并可傳參
  this.type = type      // 子類實(shí)例屬性和方法
}
Cat.prototype = new Animal()      // 原型鏈屬性和方法繼承,并支持 instanceof 指向
Cat.prototype.constructor = Cat      // 構(gòu)造函數(shù)指向,用于子類訪問父類實(shí)例屬性和方法
  1. 寄生組合繼承(剔除父類實(shí)例屬性和方法)
function Cat(name, type) {
  Animal.call(this, name)
  this.type = type
}
(function() {      // 閉包的方式,避免污染全局
  var Super = function() {}      // 空的構(gòu)造函數(shù),剔除實(shí)例屬性和方法
  Super.prototype = Animal.prototype      // 保存原型屬性和方法
  Cat.prototype = new Super()
  Cat.prototype.constructor = Cat
})()


封裝 Encapsulation

1.對事物描述的具體細(xì)節(jié)(隱私)被隱藏起來,而僅僅透露出事物的表面信息。

  • 封裝出的類 就像事物對象的說明書,僅告訴我們?nèi)绾稳ナ褂眠@個(gè)對象而已。
const Animal= function(name, secret) {
  this.name = name   // 表面信息(公共屬性)
  let secret = secret   // 被隱藏的信息(私有變量)
  let collect = function() { secret = 'collect something' } // 被隱藏的行為(私有方法)
  /* 由于閉包的特性,原型鏈中的方法無法訪問到私有變量 */
  this.exposure = function() {      // 暴露出來的表面行為(共有方法)可訪問被隱藏的信息
      this.collect()
      console.log(secret)
  } 
}


多態(tài) Polymorphism

事物衍生出來的,具有相似特性和行為的其它事物,在針對這些事物進(jìn)行描述時(shí),都具有不同的特征。

  • 多態(tài)屬于繼承的一種特點(diǎn),如從形狀繼承而來的 圓形 與 方形,他們繪制的結(jié)果卻完全不同。
const Cat = function(name,  type) {
  Animal.call(this, name)
  this.type = type
}
(function() {
  Super = function(){}
  Super.prototype = Animal.prototype
  Cat.prototype = new Super()
  Cat.prototype.constructor = Cat
  Cat.prototype.polyFunc = function() { console.log('it's cat') }     // 由派生類重寫,從而具有不同的行為
})()


ES6 中 “類” 的定義與繼承

  1. 類的定義
const privateProperty = Symbol('privateProperty')    // closure unique property identifer
const privateMethod = Symbol('privateMethod')    // closure unique method identifer
class Person {
  constructor(name) {    // constructor initial properties
      this._name = name    // initial public property
      this[privateProperty ] = 'private information'    // initial private property
  }
  get name() { return this._name }    // validate get property (use for protect members)
  set name(value) { this._name = value }  // validate set property (use for protect members)
  say() { console.log(this.name); this[privateMethod]() }    // public method, call the private method
  [privateMethod]() { console.log(this[privateProperty ]) }    // private method
  static getInformation(){ console.log('parent static method') }    // static method
}
  1. 類的繼承
class RacePerson extends Person {    // inherit the Person class
  constructor(name, from) {
      super(name)    // must call parent constructor
      this.from = from    // create and initial it's own property
   }
   say() { 
      super.say()    // call it's parent method
      console.log('from: '  + this.from)    // handle it's own logic
   }
   static getInformation() {
       super.getInformation()    // call it's parent static method
       console.log('child static method')    // handle it's own logic
   }
}

Vue 中 “類” 的定義與繼承

  1. 類的定義
const App = new Vue.extend({
  el: '#app',
  template: '<div>Hello world! {{name}}</div>',
  props: { name: '' },
  data() { return {} },
  created() { console.log('app created') }
})
  1. extends 單繼承(生命周期和watch鉤子優(yōu)先級最高,屬性和方法繼承優(yōu)先級則最低)
const ExApp = new Vue.extend({
  extends: App,    // extends 繼承中的生命周期鉤子優(yōu)先級最高,最先被調(diào)用
  data() { return { } },  // 所有派生類的同名的共有屬性將覆蓋父類的
  methods: {},  // 所有派生類的同名的共有方法將覆蓋父類的
  created() { console.log('ExApp created') },  // 派生類的生命周期鉤子優(yōu)先級最低,最后被調(diào)用
})
  1. mixins 多繼承 (生命周期和watch鉤子優(yōu)先級次于extends,屬性和方法繼承優(yōu)先級次于派生類)
const mixin1 = {
  data() { return {} },
  methods: {},
  created() { console.log('mixin1 created') }
}
const mixin2 = {
  data() { return {} },
  methods: {},
  created() { console.log('mixin2 created') }
}
const MixinApp =  Vue.extend({
  mixins: [ mixin1, mixin2 ],  // 生命周期鉤子前者優(yōu)先于后者,而屬性和方法繼承后者優(yōu)先于前者
  created() { console.log('MixinApp created') }
})
  1. inheritAttrs, $attrs, $listeners 組件式繼承(模板擴(kuò)展,父類作為模板的一個(gè)模塊)
const CompApp = Vue.extend({
  /* 父類將獲取派生類實(shí)例化時(shí)的所有沒有被繼承的屬性值和相應(yīng)事件處理方法*/
  template: '<div>{{component}}<app v-bind="$attrs" v-on="$listeners"></app></div>',
  props: { component: '' },    // 派生類繼承或擴(kuò)展的屬性
  data() { return {} },
  created() { console.log('componentApp created') },
  components: { app: App },
  inheritAttrs: false     //設(shè)置 $attrs 僅包含沒有被繼承的屬性對象(不包含派生類props定義的屬性)
})




問題

  1. 函數(shù)內(nèi)部定義方法 與 proto原型鏈中定義方法的區(qū)別
// 函數(shù)內(nèi)部定義的 實(shí)例方法 可獲取到閉包的作用域的 私有變量 和 私有方法。
const Person = function(name) {
  var name = name
  this.call = function() { console.log(name) } 
}
// prototype 原型鏈定義的 原型方法 指向其它內(nèi)存空間獨(dú)立的函數(shù)體,無法獲取閉包的作用域。
Person.prototype = {
  constructor: Person,
  say: function() { console.log(name) }
}
  1. instanceof 操作符(遞歸判斷實(shí)例原型鏈上的原型對象指向)


    JS原型鏈.jpg
function instance_of(instance, constructor) {
  var prototype = constructor.prototype      // prototype由定義時(shí)直接掛載在構(gòu)造函數(shù)上(顯式原型)
  var __proto__ = instance.__proto__        // __proto__ 指向?qū)?yīng)原型對象 prototype (隱式原型)
  while(true) {
    if ( __proto__ === null ) return false       // 匹配失敗,僅Object.prototype.__proto__為null
    if ( __proto__ === prototype ) return true   // 當(dāng)前實(shí)例原型指向與指定構(gòu)造函數(shù)匹配
    __proto__ = __proto__.__proto__         // 實(shí)現(xiàn)遞歸檢測
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??面向?qū)ο螅∣bject-Oriented,OO)的語言有一個(gè)標(biāo)志,那就是它們都有類的概念,而通過類可以創(chuàng)建任意...
    霜天曉閱讀 2,256評論 0 6
  • 博客內(nèi)容:什么是面向?qū)ο鬄槭裁匆嫦驅(qū)ο竺嫦驅(qū)ο缶幊痰奶匦院驮瓌t理解對象屬性創(chuàng)建對象繼承 什么是面向?qū)ο?面向?qū)ο?..
    _Dot912閱讀 1,536評論 3 12
  • 要拍一個(gè)專題片 完成后上交。要求并不嚴(yán)格于是偷懶決定用去年拍過的一個(gè)新聞片-校醫(yī)。吃完早餐準(zhǔn)備去再加幾個(gè)鏡頭 剛好...
    大家好我是美少女閱讀 307評論 0 0
  • 這個(gè)世上沒有兩片完全相同的葉子,也沒有兩個(gè)完全相同的人,性格有相似的,但沒有相同的。性格的形成主要源自于兒童時(shí)期,...
    無邪居閱讀 868評論 0 0
  • 由于在山里沒有信號,所以也沒辦法進(jìn)行文字的分享。選擇用徒步的方式,可能是希望能進(jìn)一步接近大自然,欣賞到美麗的風(fēng)景。...
    魚耗子閱讀 125評論 0 0

友情鏈接更多精彩內(nèi)容