Javascript 構造函數模式、原型模式

前兩天寫完組合繼承,打算總結一下原型繼承的,不過今天看了一下工廠模式、構造函數模式和原型模式,覺得有必要總結一下以加深印象。

——————————————————————————————————————————————————————————————————————————————————碎碎念。

1.工廠模式

《Javascript 高級程序設計(第3版)》 用了寥寥十多行介紹了工廠模式。我找了一些相關資料,想確定一下這種模式的具體適用場景和優勢。按照資料中的說法,是考慮到 ECMAScript 無法創建類,所以:

創建一個對象,緊接著描述對象的屬性和方法,最后用另一個對象把它們封裝起來當作接口。

按照上面描述的,工廠函數是用來在 Javascript 中實現類似于 Java 中類的功能。通過調用工廠函數,可以創建多個相似的對象實例。

? ? 簡單工廠模式:使用一個類(通常為單體)來生成實例。
? ? 復雜工廠模式:使用子類來決定一個成員變量應該是哪個具體的類的實例。

關于 Javascript 使用工廠模式的優點,根據網上的總結,大概有以下幾點:

a.?消除對象之間的耦合(這個不太明白,消除誰與誰的耦合?);

b. 在進行批次相關設置時,把所有實例化的代碼都集中在一個位置,有助于創建模塊化的代碼,減少代碼量;

c.??用于許多小型對象組成一個大對象。

缺點:

a. 沒有解決對象識別的問題。

?

.....這個模式先留著吧,沒太搞透徹優勢在哪。以后領悟了的話再來補充。引用《Javascript 設計模式與開發實踐》P5中的一段話:

“而在 Javascript 這種類型模糊的語言中,對象多態性是天生的,一個變量既可以指向一個類,又可以隨時指向另外一個類。Javascript 不存在類型耦合問題,自然也沒有必要刻意把對象“延遲”到子類創建,也就是說,Javascript 實際上是不需要工廠方法模式的。 模式的存在首先是能為我們解決什么問題,這種牽強的模擬只會讓人覺得設計模式既難懂又沒什么用。”

2.?構造函數模式

關于封裝: 在 Javascript 中,可以將一些屬性和方法封裝到構造函數內;

關于多態:在 Javascript 中不存在重載的概念,但可以通過參數個數和類型判斷來模擬重載,但是 Javascript 中多態是與生俱來的。一個最簡單的栗子:

同一個構造函數實例化得到的兩個對象實例,可以給它們傳入不同的參數,這兩個對象實例是不同的。這就是面向對象編程的多態。

利用構造函數模式,可以創建多個實例,這些實例都被標定為了特定的類型。構造函數模式相比于工廠模式更為簡單且易于實現,但也存在缺點:

function Person(name,age,job){this.name = name;this.age = age;this.job = job;this.arr = [];this.sayName = function(){alert(this.name);};
}
var person1 = new Person("Nicholas",29,"Software Engineer");
var person2 = new Person("Greg",27,"Doctor");console.log(person1.sayName==person2.sayName);//false
person1.arr.push(1);
console.log(person1.arr);//1

person2.arr.push(2);
console.log(person2.arr);//2

利用構造函數每實例化一個實例對象,構造函數內的方法都要在實例上重新創建一次。通過?person1.sayName==person2.sayName 返回的返回結果可以看到兩個實例引用的方法是不同的。

注意:這一點也適用于數組。

可以通過將構造函數的方法放在外部,使得對象實例每次都引用同一個方法。

function Person(name,age,job){this.name = name;this.age = age;this.job = job;this.sayName = sayName;
}function sayName(){alert(this.name);
}var person1 = new Person("Nicholas",29,"Software Engineer");
var person2 = new Person("Greg",27,"Doctor");console.log(person1.sayName==person2.sayName);//true

通過將構造函數的方法提到外部作為:特權方法。可以使實例獲得相同的方法引用。

但是這種方法也存在一些問題:將方法提到外部作為特權方法使得封裝性變差。如果構造函數內部有很多個方法,這樣做后果更為明顯。

另外再看一個問題:如果構造函數內有多個固定屬性,并且存在多個方法。實例化的時候要為每個對象都復制相同的固定屬性,如果將方法放在構造函數內部,這些方法也要復制,即使都作為特權函數,也存在弊端。

總結,構造函數模式存在兩點不足:1. 浪費內存;2. 可能會使封裝性變差。

3.原型模式

原型模式的出現,解決了構造函數實例化過程中對固定屬性個方法重復深復制的問題。

對于相同的屬性和方法,只要在構造函數的原型對象上申明一次,構造函數的實例就可以共享同一個屬性和方法。

function Person(){}Person.prototype.name = "Nicholas";
Person.prototype.sayName = function(){console.log(this.name);
}var person1 = new Person();
var person2 = new Person();console.log(person1.sayName===person2.sayName);//true
console.log(person1.name===person2.name);//true

?4.組合使用構造函數模式和原型模式(混合模式)

但是可以看到,雖然原型模式能夠解決固定屬性和方法多次復制的問題,如果屬性要根據不同實例對象改變,這時候最好還是把會隨實例對象改變的屬性放置在構造函數內部,這又用到了構造函數模式。將構造函數模式和原型模式相結合,就能利用這兩個模式的優勢。

function Person(name,age){//會隨實例對象改變的屬性this.name = name;this.age = age;
}
//不變的屬性或者是方法
Person.prototype.job = "Soft Engineer";
Person.prototype.sayName = function(){console.log(this.name);
}var person1 = new Person("Nicholas",28);
var person2 = new Person("Shelby",25);

?

轉載于:https://www.cnblogs.com/tisikcci/p/5846844.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457312.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457312.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457312.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2016年CCF第七次測試 俄羅斯方塊

1 //2016年CCF第七次測試 俄羅斯方塊2 // 這道小模擬題還是不錯3 // 思路&#xff1a;處理出輸入矩陣中含1格子的行數和列數4 // 再判是否有一個格子碰到底部&#xff0c;否則整體再往下移動一步&#xff0c;如果有一個格子不能移動&#xff0c;要返回到前一步5 6 #include <…

springmvc視圖解析器_SpringMVC視圖及REST風格

什么是視圖解析器&#xff1f;springMVC用于處理視圖最重要的兩個接口是ViewResolver和View。ViewResolver的主要作用是把一個邏輯上的視圖名稱解析成一個真的的視圖&#xff0c;而SpringMVC中用于把View對象呈現給客戶端的是View對象本身&#xff0c;而ViewResolver只是把邏輯…

mysql5.7.x 1251_MySql-8.0.x免安裝版下載與配置,Navicat打開數據庫鏈接報錯1251的解決辦法...

概述MySQL從5.7一下子跳到了MySQL8.0, 其中的變化必然是很大的, 這里就不說了, 本文主要講解最新版MySQL安裝的事情.實際上5.7版本后的mysql免安裝版都是沒有data文件和my.ini文件的&#xff0c;下面再具體說明怎么生成&#xff0c;注意不能自己手動新建.下載下載程序必然去官網…

To install 64-bit ODBC drivers

為了更充分的利用硬件資源&#xff0c;我想很多人都開使用64位操作系統了&#xff0c;同時你可以也發現了在64位操作系統上ODBC的驅動找不到了&#xff0c;所以ODBC的東西都沒法用了。 因為2007以前版本的Office只有32位版本&#xff0c;所以我們不能在64位系統上使用ODBC。使用…

【Qt開發】QTableWidget設置根據內容調整列寬和行高

QTableWidget要調整表格行寬主要涉及以下一個函數 1.resizeColumnsToContents(); 根據內容調整列寬 2.resizeColumnToContents(int col); 根據內容自動調整給定列寬 3.horizontalHeader()->setResizeMode 把給定列…

深入淺出mysql數據開發_深入淺出MySQL數據庫開發、優化與管理維護 PDF掃描版[513KB]...

深入淺出MySQL數據庫開發、優化與管理維護 內容介紹&#xff1a;本書從數據庫的基礎、開發、優化、管理維護4個方面對MySQL進行了詳細的介紹&#xff0c;其中每一部分都獨立成篇。本書內容實用&#xff0c;覆蓋廣泛&#xff0c;講解由淺入深&#xff0c;適合于各個層次的讀者。…

Understand Lambda Expressions in 3 minutes(翻譯)

本文翻譯自CodeProject上的一篇簡單解釋Lambda表達式的文章&#xff0c;適合新手理解。譯文后面我補充了一點對Lambda表達式的說明。 1.什么是Lambda表達式&#xff1f; Lambda表達式是一種匿名方法&#xff0c;多數情況下用來在LINQ中快速創建委托。簡單地說&#xff0c;它代表…

Hibernate二級緩存配置

一、定義&#xff1a; 二級緩存是進程或集群范圍內的緩存&#xff0c;可以被所有的Session共享&#xff0c;是可配置的插件 二、二級緩存原理圖 解析&#xff1a;每次從二級緩存中取出的對象&#xff0c;都是一個新的對象。 三、配置步驟如下&#xff1a; 同理&#xff1a;以員…

redis配置主從沒效果_跟我一起學Redis之加個哨兵讓主從復制更加高可用

Redis哨兵(Sentinel)其實本質就是一個RedisServer節點&#xff0c;通過設置 運行模式 來開啟哨兵的功能&#xff1b;主要功能如下&#xff1a;監控(Monitoring )&#xff1a;哨兵節點會不斷地檢查的主服務和從服務的運行狀態&#xff1b;自動故障遷移(Automatic failover) &…

閏秒導致MySQL服務器的CPU sys過高

今天&#xff0c;有個哥們碰到一個問題&#xff0c;他有一個從庫&#xff0c;只要是啟動MySQL&#xff0c;CPU使用率就非常高&#xff0c;其中sys占比也比較高&#xff0c;具體可見下圖。 注意&#xff1a;他的生產環境是物理機&#xff0c;單個CPU&#xff0c;4個Core。 于是&…

position定位——讓人又愛又恨的屬性

關于css中的position這個屬性&#xff0c;在使用的時候&#xff0c;有時很強大&#xff0c;有時又讓人很無奈。 強大的時候&#xff0c;對于div中的一些小物件不方便使用margin或者padding的時候&#xff0c;給與position:absolute;再配備left、right、top和bottom&#xff0c;…

CentOS 6.8安裝Python2.7.13

轉載自&#xff1a;http://www.cnblogs.com/94YY/p/6224441.html查看當前系統中的 Python 版本python --version返回 Python 2.6.6 為正常。檢查 CentOS 版本cat /etc/redhat-release返回 CentOS release 6.8 (Final) 為正常。安裝所有的開發工具包yum groupinstall -y "D…

新安裝數據庫sqlserver2008r2,使用javaweb連接不上問題處理

鼠標右鍵【計算機】--》【管理】&#xff0c;打開界面如下&#xff1a; 選擇自己數據庫的實例名&#xff1a; 選擇TCP/IP&#xff1a;右鍵【屬性】&#xff0c;將所有TCP動態端口的【0】刪掉&#xff0c;TCP端口設為1433&#xff1b;重啟服務&#xff0c;即可連接。PS:不知道這…

vue 鼠標點擊事件_VBA代碼解決方案第115講:點擊鼠標實現精準控制觸發事件的VBA代碼第二方案...

大家好&#xff0c;我們今日繼續講解VBA代碼解決方案的第115講內容&#xff1a;工作表事件中&#xff0c;根據Target參數不同&#xff0c;實現精準控制觸發事件的VBA代碼第二方案。在上一講中我們講了利用Address的屬性實現控制觸發事件的方案&#xff0c;今日講解第二方案&…

mysql注入5.0以上_[Injection]對MYSQL 5.0服務器以上版本注入

How to do a SQL Injection for MYSQL Server 5.01. Find a vulnerable add a ‘ at the end of the site example: news.php?id1 add a ‘ at the end of the 1 and see if you get a syntax error2. order by #–Keep upping the # until you get an error.3. union all sel…

動態規劃(制表法)模板及應用

int cache[100][100] 初始化為全體為 -1&#xff0c;這樣在 cache 中存儲的可以是其他任意非負整數&#xff0c;也可以是布爾類型 0/1 &#xff08;true/false&#xff09;&#xff0c;1. 模板 int cache[2500][2500];// 初始化為 -1&#xff0c;memset(cache, -1, sizeof(cach…

(翻譯)31天Windows Phone學習-1-項目模板

今天在在外文網站Google關于Windows Phone 7的學習資料&#xff0c;無疑間Google到了Jeff Blankenburg的 31 Days of Windows Phone這個系列&#xff0c;感覺寫的比較基礎和淺顯易懂&#xff0c;適合我這種入們級的人學習&#xff0c;所以準備拿來對Windows Phone 7的簡單入門學…

Mssql 跨域查詢

有數據庫test1和數據庫test2。其中test1中有表 table1、table2&#xff1b;test2 中有表 table1。三個表的字段都為為&#xff1a;id、xingming、shijian、shuliang。接下來我們就以上面的條件為例來介紹跨數據庫查詢和跨表 查詢的方法。 SELECT * FROM OPENROWSET(sqloledb…

arch mysql日志位置_MySQL 日志文件與相關參數

1 、參數文件及mysql參數查看mysql 的 my.cnf 配置文件位置命令&#xff1a;>./bin/mysql --help | grep my.cnf查看mysql 的參數設置命令&#xff1a; mysql > show variables --顯示所有參數; // show variables like log_error% 顯示某匹配參數mysql > select se…

MOSS點滴(2):自定義Application Page

在MOSS中后臺管理的頁面都是Application Page&#xff0c;比如網站設置的頁面(settings.aspx)就是典型的Application Page&#xff0c;它不能被Sharepoint Desiger定制。如果我們要修改只能手動的使用其他工具來修改&#xff0c;我們也可以添加Application Page&#xff0c;必須…