JS物件導向基礎解說(工廠模式、建構函式模式、原型模式、混合模式、動態原型模式)_javascript技巧
什麼是物件導向?面向對像是一種思想! (廢話)。
物件導向可以把程式中的關鍵模組都視為對象,而模組擁有屬性及方法。這樣我們如果把一些屬性及方法封裝起來,日後使用將非常方便,也可以避免繁瑣重複的工作。接下來將為大家講解在JS中物件導向的實作。
工廠模式
工廠模式是軟體工程領域一種廣為人知的設計模式,而由於在ECMAScript中無法建立類別,因此用函數封裝以特定介面建立物件。其實作方法非常簡單,也就是在函數內建立一個對象,給對象賦予屬性及方法再將對象傳回即可。
function createBlog(name, url) { var o = new Object(); o.name = name; o.url = url; o.sayUrl= function() { alert(this.url); } return o; } var blog1 = createBlog('wuyuchang', 'http://www.jb51.net/');
可以看到工廠模式的實作方法非常簡單,解決了創建多個相似物件的問題,但是工廠模式卻無從識別物件的類型,因為全部都是Object,不像Date、Array等,因此出現了建構函數模式。
建構子模式
ECMAScript中建構子可以建立特定類型的對象,類似Array、Date等原生JS的物件。其實作方法如下:
function Blog(name, url) { this.name = name; this.url = url; this.alertUrl = function() { alert(this.url); } } var blog = new Blog('wuyuchang', 'http://www.jb51.net/'); console.log(blog instanceof Blog); // true, 判断blog是否是Blog的实例,即解决了工厂模式中不能
這個例子與工廠模式中除了函數名稱不同以外,細心的童鞋應該發現許多不同之處:
函數名首寫字母為大寫 (雖然標準沒有嚴格規定首寫字母為大寫,但按照慣例,構造函數的首寫字母用大寫
沒有顯示的創建物件
直接將屬性和方法賦值給了this物件
沒有return語句
使用new建立物件
能夠辨識物件(這正是建構函式模式勝於工廠模式的地方)
建構子雖然好用,但也並非沒有缺點,使用建構子的最大的問題在於每次創建實例的時候都要重新創建一次方法(理論上每次創建對象的時候對象的屬性均不同,而物件的方法是相同的),然而創建兩次完全相同的方法是沒有必要的,因此,我們可以將函數移到物件外面(也許有些童鞋已經看出缺點,噓!)。
function Blog(name, url) { this.name = name; this.url = url; this.alertUrl = alertUrl; } function alertUrl() { alert(this.url); } var blog = new Blog('scjb51', 'http://sc.jb51.net/'), blog2 = new Blog('jb51', 'http://www.jb51.net/'); blog.alertUrl(); // http://sc.jb51.net/ blog2.alertUrl(); // http://www.jb51.net/
我們將alertUrl設定成全域函數,這樣一來blog與blog2存取的都是同一個函數,可是問題又來了,在全域作用域中定義了一個實際只想讓Blog使用的函數,顯示讓全域作用域有些名副其實,更讓人無法接受的是在全域作用域中定義了許多僅供特定物件使用的方法,浪費空間不說,顯然失去了物件導向封裝性了,因此可以透過原型來解決此問題。
原型模式
我們創建的每個函數都有prototype(原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。使用原型物件的好處就是可以讓所有物件實例共享它所包含的屬性及方法。
function Blog() { } Blog.prototype.name = 'wuyuchang'; Blog.prototype.url = 'http://tools.jb51.net/'; Blog.prototype.friend = ['fr1', 'fr2', 'fr3', 'fr4']; Blog.prototype.alertInfo = function() { alert(this.name + this.url + this.friend ); } // 以下为测试代码 var blog = new Blog(), blog2 = new Blog(); blog.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2,fr3,fr4 blog2.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2,fr3,fr4 blog.name = 'wyc1'; blog.url = 'http://***.com'; blog.friend.pop(); blog2.name = 'wyc2'; blog2.url = 'http://+++.com'; blog.alertInfo(); // wyc1http://***.comfr1,fr2,fr3 blog2.alertInfo(); // wyc2http://+++.comfr1,fr2,fr3
原型模式也不是沒有缺點,首先,它省略了構造函數傳遞初始化參數這一環節,結果所有實例在預設情況下都取得了相同的屬性值,這樣非常不方便,但這還是不是原型的最大問題,原型模式的最大問題在於共享的本質所導致的,由於共享,因此一個實例修改了引用,另一個也隨之更改了引用。因此我們通常不單獨使用原型,而是結合原型模式與建構函數模式。
混合模式(原型模式 建構子模式)
function Blog(name, url, friend) { this.name = name; this.url = url; this.friend = friend; } Blog.prototype.alertInfo = function() { alert(this.name + this.url + this.friend); } var blog = new Blog('wuyuchang', 'http://tools.jb51.net/', ['fr1', 'fr2', 'fr3']), blog2 = new Blog('wyc', 'http://**.com', ['a', 'b']); blog.friend.pop(); blog.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2 blog2.alertInfo(); // wychttp://**.coma,b
混合模式中建構函式模式用於定義實例屬性,而原型模式用於定義方法和共用屬性。每個實例都會有自己的一份實例屬性,但同時又共享方法,最大限度的節省了記憶體。另外這種模式也支援傳遞初始參數。優點甚多。這種模式在ECMAScript中是使用最廣泛、認同度最高的一種創建自訂物件的方法。
動態原型模式
動態原型模式將所有資訊封裝在了建構函式中,而透過建構函式中初始化原型(僅第一個物件實例化時初始化原型),這個可以透過判斷該方法是否有效而選擇是否需要初始化原型。
function Blog(name, url) { this.name = name; this.url = url; if (typeof this.alertInfo != 'function') { // 这段代码只执行了一次 alert('exe time'); Blog.prototype.alertInfo = function() { alert(thia.name + this.url); } } } var blog = new Blog('wuyuchang', 'http://tools.jb51.net'), blog2 = new Blog('wyc', 'http:***.com');
可以看到上面的範例只彈出一次窗,'exe time',也就是當blog初始化時,這樣做blog2就不在需要初始化原型,對於使用這種模式建立對象,可以算是perfect了。
此博文參考《JavaScript高級程式設計》第3版,但語言都經過簡化,例子也重寫過,如果有什麼不懂的地方請留言回复,作者將更新博客。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

如何使用Go語言實現物件導向的事件驅動程式設計引言:物件導向的程式設計範式被廣泛應用於軟體開發中,而事件驅動程式設計是一種常見的程式設計模式,它透過事件的觸發和處理來實現程式的流程控制。本文將介紹如何使用Go語言實現物件導向的事件驅動編程,並提供程式碼範例。一、事件驅動程式設計的概念事件驅動程式設計是一種基於事件和訊息的程式設計模式,它將程式的流程控制轉移到事件的觸發和處理上。在事件驅動

當物件在Jackson庫中具有父子關係時,將使用@JsonIdentityInfo註解。 @JsonIdentityInfo 註解 用於在序列化和反序列化過程中指示物件身分。 ObjectIdGenerators.PropertyGenerator是一個抽象佔位符類,用來表示要使用的物件識別碼來自POJO屬性的情況。語法@Target(value={ANNOTATION_TYPE,TYPE,FIELD,METHOD,PARAMETER})@Retention(value=RUNTIME)public

Go語言支援物件導向編程,透過型別定義和方法關聯實作。它不支援傳統繼承,而是透過組合實現。介面提供了類型間的一致性,允許定義抽象方法。實戰案例展示如何使用OOP管理客戶訊息,包括建立、取得、更新和刪除客戶操作。

Go語言支援物件導向編程,透過struct定義對象,使用指標接收器定義方法,並透過介面實現多態。物件導向特性在Go語言中提供了程式碼重用、可維護性和封裝,但也存在缺乏傳統類別和繼承的概念以及方法簽章強制型別轉換的限制。

解析PHP物件導向程式設計中的享元模式在物件導向程式設計中,設計模式是一種常用的軟體設計方法,它可以提高程式碼的可讀性、可維護性和可擴充性。享元模式(Flyweightpattern)是設計模式中的一種,它透過共享物件來降低記憶體的開銷。本文將探討如何在PHP中使用享元模式來提升程式效能。什麼是享元模式?享元模式是一種結構型設計模式,它的目的是在不同物件之間共享相同的

PHP中OOP最佳實務包括命名約定、介面與抽象類別、繼承與多型、依賴注入。實戰案例包括:使用倉庫模式管理數據,使用策略模式實現排序。

在Golang(Go語言)中並沒有傳統意義上的類別的概念,但它提供了一種稱為結構體的資料類型,透過結構體可以實現類似類別的物件導向特性。在本文中,我們將介紹如何使用結構體實現物件導向的特性,並提供具體的程式碼範例。結構體的定義和使用首先,讓我們來看看結構體的定義和使用方式。在Golang中,結構體可以透過type關鍵字定義,然後在需要的地方使用。結構體中可以包含屬

C#(CSharp)是一門強大且受歡迎的物件導向程式語言,廣泛應用於軟體開發領域。在C#開發過程中,了解物件導向程式設計(OOP)的基本概念和設計原則是非常重要的。物件導向程式設計是一種程式設計範式,它將現實世界中的事物抽象化為對象,並透過物件之間的交互作用來實現系統功能。在C#中,類別是物件導向程式設計的基本建構塊,用於定義物件的屬性和行為。在進行C#開發時,有幾個重要的設計原
