日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

深入理解面向对象 -- 基于 JavaScript 实现

發布時間:2025/7/14 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解面向对象 -- 基于 JavaScript 实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們在學習編程時,避免不了會接觸一個概念,叫:面向對象編程(Object-oriented programming,縮寫:oop) (不是搞對象那個對象哈),其實我們的編程方式,不止有面向對象,還有 面向過程編程、面向流編程、面向函數編程、面向接口編程 等。作為一名一直混跡在前端的小菜鳥,今天就來跟大家深入的探討一下 JavaScript面向對象。作為程序員,我們多多少少都會接觸自己擅長語言之外的編程語言,比如我作為一名前端,同時我還會 Java,從這兩個語言本身出發的話,我們會發現這兩種語言的 面向對象 存在著一絲絲的不同,到底哪里不同呢?我們今天就拿這兩種語言對比著來,拿具體的實例看一下,到底什么叫 面向對象編程。

現在很多文章都會講 面向對象三大特性、面向對象七原則、設計模式 等概念,今天這篇文章不準備講這些概念,從實例出發,理解 面向對象 是什么,如何做 面向對象 程序設計。

我們在深入探討 面向對象 之前,我們先來復習一下 面向過程編程,這里可能有人會問了,不是講 面向對象 嗎?為什么還要講 面向過程 呢?主要是因為,面向過程編程 是軟件思想中的鼻祖。面向過程編程 還是很好理解的,因為它是一種以 過程 作為中心的編程思想,其中 過程 的含義就是 完成一件事情的步驟。

面向過程 其實是一種 機械的思想,它就像流水線一樣,一個階段銜接一個階段,每個階段都有自己的輸入、處理、輸出,而在流水線上流動的就是我們的原料或者中間產品,每個階段都有一個機械進行處理,最后的輸出就是我們的產品。

在運用 面向過程 的方法時,你也需要設計這樣一條程序:將程序劃分為不同的階段,設計好各個階段如何銜接,然后定義好每個階段需要處理的數據。

在實際開發中,我們會把需求拆成一個一個的命令,然后串起來交給計算機去執行。舉個例子,有個需求是:在淘寶給女朋友買口紅,那么程序員接到這個命令,會列出如下幾個步驟:

  • 打開淘寶
  • 買口紅
  • 送女朋友

上面的每一個步驟,程序員都會用一個 函數 或 方法 來實現,而 函數 或 方法 是一些代碼的集合體,每個 函數 或 方法 可以實現一個功能,那么根據上述需求,我們可能會定義如下的函數:

  • openTaoBao();
  • buyLipstick();
  • sendGrilFriend();

那么程序就會順序調用了。需求完成,順利交工。但是,你覺得這樣就算結束了么?No。產品經理說:"這才剛剛開始哦~~~"。

在開始介紹 面向對象 之前,我們先來簡單概述一下,什么是 對象?對象 是一個自成一體的實體,它僅包含屬性和行為,不含任何其他內容。與面向過程的方法相比,面向對象 不在局限于計算機的機器本質,而更加側重于對現實世界的 模擬。在 面向過程 的方法中,有一套設計嚴格的操作順序,有一個類似 中央控制器 的角色來進行統一調度;而 面向對象 的方法中,并沒有明確的 中央控制器 的角色,也不需要指定嚴格的操作循序,而是設計了很多 對象,并且指定了這些 對象 需要完成的任務,以及這些 對象 如何對外界的刺激做出反應。

如果說 面向過程 像一條流水線,那么 面向對象 就像是一個籃球隊。沒有哪個人能夠在一場比賽開始的時候,就精確指定每個隊員的每一次跑動、每一次傳球、每一次投籃...而是要指定隊員的角色(前鋒、中鋒、后衛等等),然后由隊員們自己根據情況做出反應。所以說,世界上可以有兩個一模一樣的生產線,但絕對不會存在兩場一模一樣的比賽。

簡單介紹了一下 對象,現在讓我們回到上面的例子。接下來,產品經理又提了需求:

  • 在京東給女朋友買防曬霜
  • 在唯品會給麻麻買貂
  • 在蘇寧易購給爸爸買刮胡刀
  • ...

如果我們還是用 面向過程 的方法,每次需求的變更,程序員就要把整個系統通讀一遍,找出可用的函數(如果沒有就再定義一個),最后依次調用它們。最后系統越來越雜亂無章難以管理,程序員不堪重負,紛紛操起刀走上了不歸路[笑哭]...

面向對象 從另一個角度來解決這個問題,它拋棄了函數,把 對象 作為程序的基本單元。那么 對象 到底是個什么東西呢?對象 就是對 事務的一種 抽象 描述。其實現實中的 事務,都可以用 數據 和 能力 來描述。比如我要描述一個人,數據 就是他的年齡、性別、身高、體重等,能力 就是他能做什么工作,承擔什么樣的責任。描述一臺電視,數據 就是它的屏幕尺寸、亮度,能力 就是播放青春偶像劇。

面向對象 的世界里,到處都是 對象。對象 不光有 數據 和 能力 ,還可以接受命令。例如,你可以讓 貓 這個對象 吃貓糧,就可以把 吃貓糧 的命令發給 貓 讓其執行(雖然傲嬌的貓咪并不能聽你的話吧[笑哭],這里只是舉個例子),然后我們就實現了 貓吃貓糧 的需求。

現在 對象 有了,那接下來該如何進行 面向對象 的編程呢?其實很簡單,我們依次向不同的 對象 發送命令就可以了。回到上面的例子,我們用 面向對象 來實現;先定義一個 app 對象,它的 數據 就是商城名稱、商品類型等,能力 就是打開、關閉;還有一個 人 對象,它的 數據 是姓名、性別、稱謂等,能力 就是買口紅、送口紅。然后我們依次下達命令:

  • 向app下達 打開 的命令;
  • 向人下達 買口紅、送女朋友 的命令;
  • 向app下達 關閉 的命令。

其實,我們創建的對象,應該是剛剛好能做完它能做的事情,不多做,也不少做。多做了容易耦合,各種功能雜糅在一個對象里。比如我有一個對象叫 汽車,可以 載人,現在的需求是要實現 載人飛行,就不能重用這個 對象,必須新定義一個對象 飛機 來做。如果你給 汽車 插上了翅膀,賦予了它 飛行的能力,那么新來的同學面對你的代碼會莫名其妙,無從下手。

接下來,我們來看一下,上面的例子用代碼是如何實現的:

  • 首先要創建一個 App 的對象,里面包含商城名稱的數據,打開和關閉的能力:
  • 1 function App(shopName) { 2 this.shopName = shopName; 3 } 4 5 App.prototype.open = function () { 6 return `打開${this.shopName}`; 7 }; 8 9 App.prototype.close = function () { 10 return `關閉${this.shopName}`; 11 };
  • 接著我們創建一個 人 的對象,里面包含稱謂的數據,買和送的能力:
  • 1 function Person(title) { 2 this.title = title; 3 } 4 5 Person.prototype.buy = function (product) { 6 return `買${product}`; 7 }; 8 9 Person.prototype.send = function () { 10 return `送給${this.title}`; 11 };
  • 最后我們實例化對象,然后聚合我們需要的功能:
  • 1 const app = new App('淘寶'); 2 console.log(app.open()); 3 const person = new Person('女朋友'); 4 console.log(person.buy('口紅')); 5 console.log(app.close()); 6 console.log(person.send());
  • 我們來看一下最后的執行結果:
  • 基于上面的例子,我們可以看到,JavaScript 的 面向對象 是基于 原型 的,也就是 prototype,而 Java 呢?Java 是基于 類 的,也就是所謂的 class。其實不管語言對于 面向對象 是基于什么的,從概念上講,大家都是一樣的,只是我們的實現方式不同。

    在這里,我就不舉 Java 基于 面向對象 是如何實現上述實例的了,因為這篇文章講的就是 JavaScript [斜眼笑],想看 Java 的可以根據上述的文字描述自己實現一下哈,博主在這里就皮一下[笑哭]。

    抽象

    抽象 的中文概念非常形象,簡單來說就是 抽取出來比較像的部分。那么,在 面向對象 的領域里,抽取什么東西是比較像的部分?我們畫個圖來看一下 抽象 是個什么東東:

    這里的抽象分為兩個層次:

    第一個層次:對象是抽象成集合(類)
    例如:西瓜 和 蘋果 抽象成 水果,這一層的 抽象 主要是將 屬性類似 的對象抽象出來。

    注意:這里的 屬性類似 是指 屬性類別 一致,而屬性的取值是不一樣的。例如,將"西瓜"和"蘋果"都抽象成"水果",那么其屬性有顏色、重量、味道等等,但"西瓜"和"蘋果"的這些屬性取值肯定是不同的。

    第二個層次(或更高層次):將對象抽象為超集合(超類,或者說父類,就是更高一級的集合或者類)
    例如:水果 和 蔬菜 抽象成 食物,這一層的抽象主要是將 行為類似 的抽象成父集合(父類)。

    注意:這里是 行為類似,而不是第一層抽象的那樣 屬性類似,因為在 面向對象 領域,行為一致的話就認為是同一類的,當然也不能是完全不同,完全不同的話就沒有相似點,也就無法抽象成類了,所以這一層抽象的重點是 相似。

    在實際應用中,抽象的層次是不限的,根據業務需要,或者不同的觀察角度,可以抽象出很多層。

    抽象的作用

    抽象 并不是面向對象領域特有的概念和方法,在我們的日常生活和學習中,抽象 最主要的作用是 劃分類別,而 劃分類別 的主要目的其實還是關注隔離點,降低復雜度。所以,抽象是面向對象領域里面發現集合(類)的主要方法

    在JavaScript中,抽象 是允許模擬工作問題中通用部分的一種機制。這可以通過繼承(具體化)或組合來實現。JavaScript通過 繼承 實現 具體化,通過讓類的實例是其他對象的屬性值來實現組合。
    JavaScript Function類 繼承自 Object類(這是典型的具體化)。Function.prototype 的屬性是一個 Object實例(這是典型的組合)。

    多態(polymorphism)

    引用 MDN web docs 中的一段話來描述一下 JavaScript多態:

    就像所有定義在原型屬性內部的 方法 和 屬性 一樣,不同的類可以定義具有相同名稱的方法;方法是作用于所在的類中。并且這僅在這兩個類不是父子關系時成立(繼承鏈中,一個類不是繼承自其他類)。

    [笑哭]大家看完這段話之后,是不是覺得很懵,這是在說什么啊,什么類,什么繼承。不著急哈,接下來我會詳細解釋一下在 JavaScript 中,多態究竟是怎么樣的存在哈...

    polymorphism,翻譯成中文:多態性,我們從字面意思上就可以看出,多態 就是 多種形態 的意思。但仔細探究一下:多種形態 其實還是沒法很好的理解,不同的人也還是有不同的理解。

    動畫片看得多的同學可能會以為:多種形態,就是很多種變身,就像孫悟空72變一樣,一會兒可以變成房子,一會兒可以變成牛魔王;
    擅長打扮的美女可能會以為:多種形態,其實就是換不同的衣服嘛,一會兒文藝小清新打扮,一會兒高貴典雅的貴婦裝束;
    學院派技術宅男可能會以為: 多種形態,其實就是多種狀態啦,比如說TCP協議棧有XX種狀態...

    可能還有很多其它各種各樣的理解,但在 面向對象 領域,這些理解都不正確,多態不是變身、換裝、狀態變化,而是多胎...

    哇!!博主你打錯字了,怎么可能是 多胎呢?這是什么意思啊?

    其實,多胎 在這里也是一個形象的說法,在 面向對象 領域,多態 的真正含義是:使用指向父類的指針或者引用,能夠調用子類的對象

    我要是在這里引用 Java 代碼,會不會引起公憤[笑哭],還是乖乖的用 JavaScript 來寫個 多態 的例子:

  • 首先建一個 Person 對象:
  • 1 // 定義Person構造器(類) 2 function Person(personName) { 3 this.personName = personName; 4 } 5 6 // 在Person.prototype中加入study方法 7 Person.prototype.study = function () { 8 return `${this.personName}學習語文`; 9 };
  • 然后創建一個 Boy 對象,并且繼承自 Person 對象,修改原先 Person 對象中的方法:
  • 1 // 定義Boy構造器(類) 2 function Boy(personName) { 3 // 調用父類構造器,確保"this"在調用過程中設置正確 4 Person.call(this, personName); 5 } 6 7 //建立一個由Person.prototype繼承而來的Boy.prototype對象 8 Boy.prototype = Object.create(Person.prototype); 9 10 // 設置"constructor"屬性指向Boy 11 Boy.prototype.constructor = Boy; 12 13 // 更換"study"方法 14 Boy.prototype.study = function () { 15 return `${this.personName}學習數學`; 16 };
  • 再然后,創建一個 Girl 對象,也讓它繼承自 Person 對象,繼續修改原先 Person 對象中的方法:
  • 1 // 定義Girl構造器(類) 2 function Girl(personName) { 3 Person.call(this, personName); 4 } 5 6 //建立一個由Person.prototype繼承而來的Girl.prototype對象 7 Girl.prototype = Object.create(Person.prototype); 8 9 // 設置"constructor"屬性指向Girl 10 Girl.prototype.constructor = Girl; 11 12 // 更換"study"方法 13 Girl.prototype.study = function () { 14 return `${this.personName}學習英語`; 15 };
  • 創建一個執行函數:
  • 1 // 這個參數就是"多態"的具體表現形式 2 const test = function (person) { 3 // 在調用person.study()的時候,函數并不知道person究竟是Boy,還是Girl,只知道是個對象 4 console.log(person.study()); 5 }; 6 7 // 執行test方法 8 test(new Boy('Tom')); 9 test(new Girl('Jenny'));
  • 最后我們看一下執行結果:
  • 嗯,沒錯,是我們想要的結果[嘿嘿]。那接下來,我們在來看一下,如果不用 多態,上述的例子要怎么寫。

  • 好,先創建一個執行對象那個:
  • 1 // 定義一個執行的構造器(類) 2 function Test() {} 3 4 // 在Test.prototype原型中加入boyStudy方法 5 Test.prototype.boyStudy = function (boy) { 6 console.log(boy.study()); 7 }; 8 9 // 在Test.prototype原型中加入girlStudy方法 10 Test.prototype.girlStudy = function (girl) { 11 console.log(girl.study()); 12 };
  • 在創建一個 Boy 對象:
  • 1 function Boy(boyName) { 2 this.boyName = boyName; 3 } 4 5 Boy.prototype.study = function () { 6 return `${this.boyName}學習數學`; 7 };
  • 在創建一個 Girl 對象:
  • 1 function Girl(girlName) { 2 this.girlName = girlName; 3 } 4 5 Girl.prototype.study = function () { 6 return `${this.girlName}學習英語`; 7 };
  • 最后,我們調用執行對象,輸出這兩個對象的數據:
  • 1 const test = new Test(); 2 3 test.boyStudy(new Boy('Tom')); 4 5 test.girlStudy(new Girl('Jenny'));

    當然最后的執行結果肯定是一樣的,那讓我們來看一下,這兩種寫法到底有什么區別:

    • 首先,最開始的那個例子,我們用了個 test 函數,注釋也寫了,不需要關心對象具體是哪個,只要對象包含需要調用的方法就OK;
    • 而第二個例子呢?我們仔細看一下,第二個例子現在看起來很清晰,但是不利于擴展,為什么?關鍵點在執行函數中,如果我要是在加了 女人、 男人 這兩個對象的話,那是不是還得在 Test 對象里面在添加兩個對應的執行方法?答案是肯定的,不然沒地方執行呀。
    • 所以說,這就是 多態 的特點。

    有興趣的同學還可以用 es6 語法的 class、extends 來寫一下上述的例子,我這里就不在贅述了。

    我們說了這么多,主要是想講述一下在 JavaScript 中,是怎么體現這些思想的,我最想說的一句話就是:JavaScript 是基于 原型 的語言,也希望大家能一直記住這句話。

    而 Java 呢,是基于 類(class) 的語言,這兩種語言從語法上就有本職的區別,但是概念性的東西,是不會變的。我們應該拋開語言層面,更進一步的去學習面向對象的概念,然后在從語言上下手,學習如何實現這一概念。

    啊哈,對了,突然想到,雖然現在對于前端來說,JavaScript 挺重要的,但是我們大多數同學在開發時,會用到三大框架的其中之一(react、vuee、angular),也有可能都用過,我們大多數人把關注點都放在了 JavaScript,而忽略了我們的 html + css 也是有 面向對象 概念的。今天就拿 vue 中的組件概念,來簡單說說 模板 是如何實現 面向對象 的。

    不知道用 vue 做過開發的同學們,記不記得組件有個概念叫 動態組件[斜眼笑]。對,就是那個 <component></component>,需要通過 is 屬性來加載不同的組件。這里就不在具體舉例子講這個東西怎么用了,但是它就是 多態 的一種的實現形式,component 不會關心你的組件都有什么(作用相當于上述js例子的test函數),知道你傳過來的數據,我能匹配上,找到你想要的那個結果就好了。官方舉的例子是關于 tab 進行動態切換時,不管加幾個標簽,對本身功能并不會有影響,只需要多建幾個模板就好了。

    好了,就講這么多吧,對 Java 感興趣的同學,可以根據上述的例子,用 Java 來寫一下,體驗一下 面向對象、多態 的快感,啊哈哈~~~

    轉載于:https://www.cnblogs.com/liuqiuyue/p/11216951.html

    總結

    以上是生活随笔為你收集整理的深入理解面向对象 -- 基于 JavaScript 实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。