1. 程式人生 > 實用技巧 >【面向物件】面向物件程式設計思維(二)

【面向物件】面向物件程式設計思維(二)

前言:
  上一章我們用大白話講解了一下面向物件的程式設計思維,那麼這一張我們來講講如何用面向物件來書寫程式碼。終於到了激動人心的時刻了.....

  傳送門:http://www.cnblogs.com/nanianqiming/p/7710986.html 上一篇的地址
面向物件的三大特徵:
  在瞭解了面向物件的程式設計思維後我們繼續瞭解下面向物件的三大特徵從而深刻的理解一下面向物件

  抽象:抓住核心問題
      如何想描述一個人的時候我們應該如何去描述?用不用把這個人的每一個身體的器官,以及每一段經歷都書寫出來?那麼我敢說你要是想了解我的話,你至少的寫2本書才能把我
      描述出來,但是在我們面向物件的三大特徵中的抽象就不需要這麼麻煩,你只需要知道我這個人的姓名,年齡,外貿,以及一些主要的資訊就可以了。也就是說你只需要把問題
      的核心部分拿到手裡面就可以了,這就是所謂的抽象


  封裝:不考慮內部實現,只考慮功能使用
      當我們駕駛汽車的時候,是否要知道發動機的原理?
      當我們開啟電視機的時候,是否要知道它的電路結構?
      當我們玩電腦的時候,是否要精通計算機的硬體組成?
      當我們打遊戲的時候,是否必須明白程式的實現原理?
      其實以上一些問題我們都不需要去了解內部的一些構造,其實封裝也是如此:把一些功能封裝好,留一個用口

  繼承:從已有的物件上繼承出新的物件
      說到繼承,不得不說下我自己,我一直以為我的家族是一個擁有億萬資產的龐大家族,而我現在所經歷的一切都是父親給我安排好的磨練,如今快過了小三十年了。我才發現我
      想多了,其實繼承最好理解就是你可以繼承你父親的遺產,或者你父親的一些面貌特徵,程式設計也是如此

  多型:哈哈哈,你們很慶幸,因為javascript中沒有多型


好了瞭解完面向物件的三大特徵,那麼下面我們真的真的來看看面向物件是如何編寫程式碼的
建構函式:
  首先我們先來聊一聊建構函式,等下?不是說要講如果用面向物件的思維來編寫程式碼嗎?怎麼現在又扯到了建構函式?
  不要著急小夥子,我們一步一步來,因為面向物件的程式設計風格都是從一個關鍵字 new 開始的

什麼是建構函式?
  通過new 呼叫的函式 叫做建構函式

  在講建構函式的時候我們先來想一個問題,如何建立一個物件?聽到這個問題有些同學就安奈不住自己拿躁動的小心靈了,這還不簡單?
  var obj = new Object();
  var obj = Object();
  var obj = {};
  
  好既然這麼厲害,那我的要求再次升級,能不能用你知道的物件給我描述一個人?這是時候你又安奈不住你幼小的心靈了!!!
  var obj = {
      name:"凡塵",
      age:"18",
      sex:"帥哥",
      show:function(){
        console.log("凡塵是個大帥哥")
      }
    }

  是不是感覺分分鐘就寫完了?那麼好,我的需求在此升級,你給我描述10個人的資訊!!!這時候你是不是就開始複製貼上了?然後貼上了滿屏的程式碼?這又是何苦呢?
  難到我們就不能封裝一個嗎?

  function person(name,age,sex){
    
    var obj = new Object();
  
    obj.name = name;
    obj.age = age;
    obj.sex = sex;

    obj.showName = function(){
      console.log("我的名字叫"+this.name)
    }

    obj.showAge = function(){
      console.log("我的年齡"+this.age)
    }

    return obj;
  }
  -----------------------------------------------------------------------------------------------------------------------------------------------
  這時候你是不是感覺你又行了?感覺你特別厲害了?其實這種方式其實就是一個工廠函式,我們可以逐步的接下一下
 function person(name,age,sex){
    //原料
    var obj = new Object();
    //加工
    obj.name = name;
    obj.age = age;
    obj.sex = sex;

    obj.showName = function(){
      console.log("我的名字叫"+this.name)
    }

    obj.showAge = function(){
      console.log("我的年齡"+this.age)
    }
    //出廠
    return obj;
  }
這時候是不是問題就完美的解決掉了呢?不不不,問題才剛剛開始,因為我剛才說過了面向物件的程式設計風格都是從一個關鍵字 new 開始的 很明顯我們在呼叫這個函式的時候根本沒有用到
new這個關鍵字。

那麼問題又來了,為什麼非要扯上這個new 難到沒有這個new就不行嗎?不要急躁我們一步一步來

首先我們把問題列出來看看問題在哪?

  1、在呼叫這個函式的時候我們沒有用 new 而new這個關鍵字在函式的內部使用了。那麼我們能不能把這個new給拿出來?

  2、上面的栗子中有一個showName方法。那麼每次呼叫這個方法的時候showName方法是否為同一個方法?
    如:var b1 = person(name,age,sex); var b2 = person(name,age,sex);
      alert(b1.showName == b2.showName)//false

既然問題列出來了,那麼我們就去解決這2個問題






  1、在呼叫這個函式的時候我們沒有用 new 而new這個關鍵字在函式的內部使用了。那麼我們能不能把這個new給拿出來?

  問題一:
    為什麼我非要在呼叫函式的時候要加一個new呢?好我來解決下這個問題

   

    通過這張圖我們很明顯就可以看出了區別:

      普通函式呼叫的時候this的指向是window 而建構函式呼叫的時候this的指向是這個物件

     普通函式沒有return的時候返回值是undefined  而建構函式的返回值想自己本身這個物件 

   為什麼建構函式沒有return卻能夠有返回值呢?
      因為建構函式在呼叫的時候系統內部自動return出了一個this,而這個this就是指的這個物件
 

   現在我們知道了呼叫函式的時候加new 和不加new的區別了那我們就來改上面的程式碼!
    

  

列印結果是:凡塵 18

好累啊!!!!終於解決完第一個問題了,那麼我們繼續來解決第二個問題

 2、上面的栗子中有一個showName方法。那麼每次呼叫這個方法的時候showName方法是否為同一個方法?

  我們先來驗證一下是否為同一個方法

為什麼會是一個false呢???如果你聽過凡塵老師講課的話,在ES6的一張說過一道面試題。

建立建構函式的時候js執行了那些操作?

1、在記憶體中開闢了一塊空間 2、把this的指向指向了它 因為new一次就會開闢一塊空間,你還指望他們相等嗎?就相當於你蓋了一個房子,然後買了一個100英寸的電視,然後你發小也蓋了一個房子,然後也買了一個100英寸的電視,你難到能說他加的 電視就是你家的電視嗎?

既然知道了問題的所在那麼我們就去解決這個問題。接下來我們在去扯扯陣列

我們都知道陣列有好多方法共我們使用,例如 push pop shift.....那麼陣列有沒有一種去重的方法共我們使用呢?例如就叫norepeat?

不用試也應該知道根本沒有這個方法。那麼我們可不可以給陣列加上這個方法呢?當然可以,首先我們要先知道push pop shift....等這些東西在陣列的哪裡放著。接下來我們學習一個

新的東西叫原型----prototype

我們在頁面上輸出這樣一句話,Array代表陣列,也就是說來看下陣列的原型。我看可以看下打印出來了什麼東西;

你會發現你找到了一個窩點,裡面有好多我們熟悉的方法。那麼我就可以肯定陣列的那麼方法是加在原型上面的。那麼我們接下來就給陣列新增一個norepeat方法

那麼別的陣列可以使用這個方法嗎?他們這個方法是一樣的嗎?接下來我們去驗證這個問題!!!!

經過驗證準確無誤!!!大功告成,這樣我們終於把這兩個問題解決完了,那麼我們在從新寫下我們最開始的那個工廠函式

終於完成了!!!!碼字碼的好辛苦!!!等這不是說帶我們用面向物件的思維寫程式碼嗎?怎麼就結束了呢?

其實上面的過程和步驟就是利用面向物件的思維去寫的,我們稍微總結一波你們就懂了

  1、以前我們的全域性變數都是為一個人進行服務的,但是現在我們把變數變成了屬性,面向物件就可以對所有的人進行服務,而且全域性變數會讓你的程式變的特別慢,其實你也可以理解成
    婚前誰也不屬於誰,但是婚後你就只屬於對方了

  2、我們把所有的函式都加在了物件的原型上面,其實就相當於就每一個方法分割成了不同的模組。這個正好就是我們面向物件的程式設計思維


截止到目前為止除了面向物件的繼承沒有講到以外,其他的應該都已經說到了。如何你能接受這個兩篇文章那麼你就能用面向物件的思維去編寫程式了!!!



具體如何用 面向物件寫程式呢?我大致分為以下幾個步驟

  1、把面向過程的程式,改寫成面向物件的形式   2、改寫成面向物件的幾個條件   a、所有的東西寫在onload裡面   b、不能有函式巢狀,可以有全域性變數   3、 全域性變數---》屬性 函式---方法 onload ====建構函式   4、改錯