天天看點

JavaScript進階(1) 面向對象 (多圖)

因為之前學過類,是以聽起來還比較輕松,但是初學者(以前的我 - >-)可能會有點懵逼,建議先在網上好好查閱資料

面向對象程式設計

面向過程程式設計

面向過程程式設計就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實作,使用的時候再一個一個依次調用就可以.面向過程,就是按照我們分析好的步驟,按照步驟解決問題

面向對象程式設計

面向對象是把事物分解成為一個個對象,然後由對象之間分工與合作.面向對象是以對象功能來劃分問題,而不是步驟

在面向對象程式開發思想中,每一個對象都是功能中心,具有明确分工.

面向對象程式設計具有靈活,代碼可複用,容易維護和開發的優點,更适合多人合作的大型軟體項目.

面向對象的特性

  • 封裝性
  • 繼承性
  • 多态性

類(class)

(仿佛回到了學Python的時候...)

在ES6中新增了類的概念,可以使用class關鍵字聲明一個類,之後以這個類來執行個體化對象.

類抽象了對象的公共部分,它泛指某一大類

對象特指某一個,通過類執行個體化一個具體的對象.

面向對象的思維特點

  • 抽取(抽象)對象共有的屬性和行為組織(封裝)成一個類(模闆)
  • 對類進行執行個體化,擷取類的對象

建立類

JavaScript進階(1) 面向對象 (多圖)

建立執行個體

var xx = new name( )

類必須要用new執行個體化對象

完整寫法:

class name {
        // class body
    }
    var xx= new name();           

複制

類constructor構造函數

constructor()方法是類的構造函數(預設方法),用于傳遞參數,傳回執行個體對象,通過new指令生成對象執行個體時,自動調用該方法.如果沒有顯示定義,類内部會自動給我們建立一個constructor()

JavaScript進階(1) 面向對象 (多圖)

隻要有new就會自動調用constructor( )這個方法.我建立ldh對象時将"劉德華"這個參數傳遞給了uname,而uname又指派給了this.uname;this指向的是我們建立的執行個體,this.uname就是我建立的執行個體ldh的uname.我将"劉德華"指派給我們的執行個體的uname,是以ldh這個執行個體化對象的uname就是"劉德華".(有點繞...),反正就是我建立了一個明星類,然後執行個體化了一個ldh對象,并且給他的uname指派為劉德華.

注意:

  1. 通過class關鍵字建立類,類名我們還是習慣性定義首字母大寫
  2. 類裡面有個constructor函數,可以接受傳遞過來的參數,同時傳回執行個體對象(是以不用return就能列印出對象)
  3. constructor函數,隻要 new 生成執行個體時,就會自動調用這個函數.如果我們不寫這個函數,類也會自動生成這個函數
  4. 生成執行個體new不能省略
  5. 最後注意文法規範,類名後面不要加小括号,生成執行個體,類名後面加小括号,構造函數不需要function.

類添加方法

JavaScript進階(1) 面向對象 (多圖)

注意: 類裡面的方法不需要寫function;多個方法函數之間不需要逗号分割!!

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

類的繼承

子類可以繼承父類的一些屬性和方法

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

下面我們看看這個情況:

子類繼承了父類的方法,自己重寫了屬性,但是想繼續使用父類的方法sum()

JavaScript進階(1) 面向對象 (多圖)

按理來說應該得到3這個答案,但是結果是報錯

JavaScript進階(1) 面向對象 (多圖)

這是因為我們sum()方法中的this指向的都是父類的對象,但是子類重寫了,this指向的就是子類的對象了,是以當然會報錯

這個時候就要用到super()了

super關鍵字

super關鍵字用于通路和調用對象父類上的函數.可以調用父類的構造函數,也可以調用父類的普通函數.

我們隻要将函數這樣修改就可以了

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

這樣就可以啦

super()不僅能繼承構造函數,也能繼承普通函數

我們看下面的例子:

JavaScript進階(1) 面向對象 (多圖)

毫無疑問會輸出"我是兒子?imageView2/2/w/1620",因為兒子重寫了這個方法

JavaScript進階(1) 面向對象 (多圖)
  1. 繼承中,如果執行個體化子類輸出一個方法,先看子類有沒有這個方法,如果有就先執行子類的.
  2. 繼承中,如果子類裡面沒有,就去查找父類有沒有這個方法,如果有,就執行父類的這個方法(就近原則)

改成這樣即可:

JavaScript進階(1) 面向對象 (多圖)

現在我們寫一個子類,繼承父類的加法運算,同時有自己的減法運算方法:

JavaScript進階(1) 面向對象 (多圖)

但是這樣會報錯:

JavaScript進階(1) 面向對象 (多圖)

在這裡要注意,利用super調用父類的構造函數,super必須在子類this之前調用!!!

JavaScript進階(1) 面向對象 (多圖)

應修改為:

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

這樣就沒問題了

注意:

  1. 在ES6中類沒有變量提升,是以必須先定義類,才能通過類執行個體化對象
  2. 類裡面的共有的屬性和方法一定要加this使用.
  3. constructor裡面的this指向執行個體對象,方法裡面的this指向這個方法的調用者
JavaScript進階(1) 面向對象 (多圖)

注意: sing這個函數如果不加括号就不會立即調用,加了就會立即調用:

比如這個方法,我們是要點選了才調用,加了就會立馬調用

JavaScript進階(1) 面向對象 (多圖)

this指向問題

在constructor()方法中,this指向的是我們new出來的執行個體化對象

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

順便解決了前面的問題,為什麼列印出來的uname是undefined:因為this指向的是button,button的uname當然沒有定義,是以就是undefined.

JavaScript進階(1) 面向對象 (多圖)

那要怎樣才能點選button以後擷取到constructor裡面的uname呢?隻要在外面聲明一個全局變量,再将this指派給它就可以了.

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

接下來就是案例時間: tab欄切換

JavaScript進階(1) 面向對象 (多圖)

需求:

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

是以我們可以先寫一個Tab類出來,裡面具有多種功能(方法):

JavaScript進階(1) 面向對象 (多圖)

擷取要操作的元素

JavaScript進階(1) 面向對象 (多圖)

初始化綁定事件

JavaScript進階(1) 面向對象 (多圖)

在點選時就切換類,給點選的li和section設定類名.

我們在前面講過,想要調用constructor()裡面的屬性,需要聲明一個全局變量,是以我們聲明一個that:

JavaScript進階(1) 面向對象 (多圖)

類裡面的方法隻能由對象本身調用,是以才要将this指派給that

JavaScript進階(1) 面向對象 (多圖)

現在切換功能就基本實作了,接下來是添加功能

JavaScript進階(1) 面向對象 (多圖)

我們先将添加的按鈕綁定事件:

JavaScript進階(1) 面向對象 (多圖)

接下來要做的:

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

初步做出來是這樣的

JavaScript進階(1) 面向對象 (多圖)

我們先來看看效果:

JavaScript進階(1) 面向對象 (多圖)

肯定是有bug的,後面的新增的li并沒有切換功能,且下面的内容也全部出來了,這是因為我們一開始擷取的li和section都是本身存在的,初始化時都綁定了事件,但是我們後來生成的li和section都沒有被擷取,自然也沒有綁定事件

JavaScript進階(1) 面向對象 (多圖)

然後在元素都添加完以後調用init初始化一遍,新增的元素就綁定了事件

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

那麼添加功能就完成啦,現在做删除的功能

JavaScript進階(1) 面向對象 (多圖)

首先還是擷取元素:

JavaScript進階(1) 面向對象 (多圖)

然後在循環中綁定事件:

JavaScript進階(1) 面向對象 (多圖)

編輯删除方法:

JavaScript進階(1) 面向對象 (多圖)

但是這個時候我們點選添加按鈕時卻出錯了:

JavaScript進階(1) 面向對象 (多圖)

分析一下:

當我們頁面一加載,就擷取所有的關閉按鈕,一開始隻有三個,但是當我們點選添加按鈕時,這時候調用了addTab(), addTab裡面又有init(),是以目前有4個li,但是每個li都要周遊:remove的關閉按鈕隻有三個.

JavaScript進階(1) 面向對象 (多圖)

是以解決方案就是将擷取關閉按鈕元素的代碼寫在update方法裡面:

JavaScript進階(1) 面向對象 (多圖)

然後是删除方法:

JavaScript進階(1) 面向對象 (多圖)

有點難qwq...最後一個短路運算也是我随便試出來的..

終于到了最後的編輯功能!

JavaScript進階(1) 面向對象 (多圖)
JavaScript進階(1) 面向對象 (多圖)

編輯事件

JavaScript進階(1) 面向對象 (多圖)

很幸運,section的做法和span一模一樣,隻要加一行代碼就可以了

JavaScript進階(1) 面向對象 (多圖)

這個案例到這裡就結束啦,真的很累,也學到了很多!!!現在看看功能

切換:

JavaScript進階(1) 面向對象 (多圖)

添加和删除

JavaScript進階(1) 面向對象 (多圖)

編輯:

JavaScript進階(1) 面向對象 (多圖)

困暈了,休息一下,到時候将這個案例複習一遍!(想想就好累...)