2016年3月12日 星期六

一個構思,二十四小時的堅持

昨天凌晨想到希望能在 PowerDesigner RQM ,讓使用者可以選取某一字串並把它傳到 Clipboard ,VBS 在到 Clipboard 裡取出,然後建立 Glossary Class

User 選取字串後,按右鍵點選選單上的功能,透過 SendKeys("^{c}") 可以模擬 copy 的動作,並將該字串送到 Clipboard ,但發現VBS 並不支援 Clipboard 物件,且執行完SendKeys("^{c}") 馬上去進行讀取動作,好像 SendKeys("^{c}") 也有問題,一定要有延遲的指令才可以, VBS  也無Sleep 指令

經過一整天的測試和尋找資料,終於找到解決的方法,方法如下 

選取字串後執行

Dim WshShell,objHTM, ClipboardText ,strClipboard

   set WshShell= CreateObject("WScript.Shell") 

   WshShell.SendKeys("^{c}")  ‘將選取的字串送到 Clipboard  

  WshShell.Run " ",0   '一定要執行,資料才會真的寫到Clipboard ,延遲時間,利用空字串,就不會一定執行一個程式

   '確實可以取得 Clipboard 裡的資料,因為vbs 沒支援使用 Clipboard 物件,所以利用htmlfile 來間接取得Clipboard 的資料

   Set objHTM = CreateObject("htmlfile")

  strClipboard = objHTM.ParentWindow.ClipboardData.GetData("Text")    

  ClipboardText=""+strClipboard+"

msgbox  ClipboardText

   set WshShell=Nothing

   set objHTM=Nothing

經過二十四小時馬拉松式的測試,終於找到的解法方法,真是大快人心

2016年3月10日 星期四

實穫價值分析

    實穫價值分析(earned value analysis) 於專案績效控制方面是一個很重要的工具。它將成本與時程整合為同一種貨幣的單位。根據統計,一般專案進行到 15% ,將可準確的預估未來的績效。它的價值在於專案管控週期中可以明確知道目前的績效狀況,對變異的狀況來做管理活動與矯正措拖,更進一步的可以利用目前的績效狀況來預估未來的績效,並適時採取矯正行動,提供一個早期預警的功能。也就是說可用來衡量專案的進度,並預測其完成日期與最終的成本,以提供觀測時程與成本在專案過程中的變化。
      
所謂的實穫價值,是指已完成工作之價值。實穫價值分析是利用三個指標數字來評估並比較專案的進展,分別是:
BCWP(Budgeted Cost of Work Performed):已完成工作之預算成本

    這就是所謂的實穫價值對於已完成之工作而言,它為專案所獲得的價值,就是原先分配給它的預算,也就是用來完成該工作之預估成本。(沒有考慮時間只考慮完成了多少)可用來評估實際上有多少工作是已經完成的

BCWS(Budgeted Cost of Work Scheduled):依時程工作之預算成本
     這代表從專案開始到分析日為止,應該完成的工作,或者應該用掉的預算有多少
。計算方法如下:
       
BCWS=總預算X用掉之時間/專案時程

ACWP(Actual Cost of Work Performed):已完成工作之實際成本

     代表直到分析日之前,已完成工作之實際成本或花費

有了上述三個基本指標做母數,便可產生許多衍生指標來衡量專案的進度,以及時程與成本在專案過程中的變化


時程變異(Schedule Variance,SV)=BCWP-BCWS(負值表示進度落後)
時程績效指標(Schedule Performance Index,SPI)=BCWP/BCWS(小於1.00 表示時程落後)
成本變異(Cost Variance,CV)=BCWP-ACWP(負值表示預算超支)
成本績效指標(Cost Performance Index,CPI)=BCWP/ACWP(小於 1.00 表示預算超支)
原始總預算(Budget At Completion,BAC)=即預日完工日之 BCWS
預估總預算(Estimate At Completion,EAC)=即累計已花費+預期直到完工之花費 公式為:
   

 



預估最終成本之變異(Variance At Completion,VAC)=BAC/EAC
    上述指標,定期追蹤一段時間後,便可得到一張收穫價值圖,讓人一目了然知道專案現在的進度位置,以及過去歷史與中間的變化




實穫價值分析的優點是簡單可行,因為它所衡量的是專案的花費或數量,這些都是已知的資料。其缺點是它的衡量單位是金錢不是時間,但往往專案同時也在)。意時間,也就是專案是否能如期完成? 所以雖然在預估專案完工成本上,一般採用的指標為成本績效標(CPI), 然而如果因為時程延宕的關係而造成專案完工成本的變動,則要將時程指標也考慮進來,而會影響時程的作業,通常是位於專案要徑(critial path)上的活動故很多學者也將時程績效指標納入預估完工成本的計算,一般常見到的績效指標大致分成以下四種型式(Christensen1993)

      
(1) Cost Performance Index = CPI = BCWP/ACWP

(2) Schedule Performance Index = SPI = BCWP/BCWS

(3) Schedule Cost Index = SCI = SPI × CPI

       (4) Composite Index = W1 × SPI + W2 × CPI, where w1+w2=1

經由許多的實證研究說明預估完工成本所使用的績效指標若為CPI將會建立一個下限的範圍,而使用SPI × CPI將會建立一個上限範圍,而SPI × CPI所預估的完工成本會如此龐大,是因為一般的專案通常都是成本超支且進度落後。而在Composite Index,許多學者都以不同的權重組合(0.2SPI+0.8CPI)作分析,而大多數的預估完工成本都會落在上下限之中(如圖)


其中的權重績效指標則是考慮了要徑因素。其做法是
一. 判斷造成時程變異之作業(Activites)是否為要徑上的作業?
a.       若造成時程變異之作業非要徑上之作業:代表控週期中的作業並不影響專案預定的進度,所以此狀況下,只要以 CPI 指標為預估完工成本的績效指標就可。
b.        若造成時程變異之作業為要徑上之作業:代表管控週期中的作業可能會影響整個專案的進度,故時程績效指標是有必要納入預估完工成本的考量,所以在此狀況下使用權重績效指標(WPI)為預估完工成本的績效指標。
二.將一的 (A)、(B) 結合,以 PI 表示,得到如下的表示法:
一般預估完工成本可以寫成以下的通式,PI 可為不同的績效指標,而一般最常用的為  CPI:

PIperformance index

只考慮成本變異的CPI有不足之處,將成本與時程變異的相對影響程度建構WPI:


WPI:weighted schedule cost performance index
故新的預估完工成本公式如下:


在考慮時程變異的同時,須先考慮要徑的問題,故將要徑因素納入,結合上述步驟一建議的兩個情況,本模式將修正為:




預估完工成本的準確度本研究將定義為:




 名詞解釋:
(1) PV(Planned Value)Cost Variance):預計成本;代表預計在某時間點所應花費的成本。
(2) EV(Earned Value)實獲值;代表在某時間點實際獲得的價值。
(3) AC(Actual Cost)
實際成本;在某時間點實際花費的成本。
(4) CV(
成本變異;實獲值與實際成本之差,大於
0為佳。
(5) SV(Schedule Variance):時程變異;實獲值與預計成本之差,大於0
為佳。
(6) CPI(Cost Performance Index)
成本績效指標;實獲值與實際成本的比值。
(7) SPI(Schedule Performance Index)
時程績效指標;實獲值與預計成本的比值。
(8) WPI(Weighted Schedule Cost Performance Index)
:權重績效指標;結合成本與時程變異相對權重的績效指  
      標。
(9) PI(Performance Index)
績效指標通式,可依情況選擇性使用績效指標。
(10) BAC(Budget at Completion)預算總成本

(11)VAC(Variance at Completion)完工成本差異,為預估完工成本與預算總成本之差。 
(12) EAC(Estimate at Completion)
預估完工成本,由變異狀況預測未來所需之成本。 
(13) 準確度實際完工總成本與預估完工成本的比值

2016年3月9日 星期三

為什麼要用 UseCase 來捕獲需求?

    Q: 使用者說他希望系統能有新增客戶訂單的功能,這不就是需求了嗎?為什麼還要用 UseCase 去描述需求?(兼談為什麼不要將功能列表或系統特性清單當成系統需求)


A: 假如你要去高雄,你會經過那幾個城市

 

最常的走法

台北、桃園、新竹、苗栗、台中、彰化、嘉義、台南、高雄。

有時的走法

台北、桃園、新竹、苗栗、台中、彰化、南投、嘉義、台南、高雄。

另一種特別的走法

台北、基隆、宜蘭、花蓮、台東、屏東、高雄。

塞車的走法

………

 

究竟您會採取那一種路徑,有時是依您的意圖;有時是依當時的情況;更多的時候是限制於某些條件。但不管怎樣,雖然有那麼多不同的路徑,但目的是相同的,都是到達高雄(:這裡沒有討論使用那一種交通工具,因為那是How to 的問題,Use Case 只描寫 What,做些什麼的事)。看似一句簡單的陳述,往往隱藏著多種可能,如果我們在還沒探究此目的下存在的多種不同路徑,就去估算達成此目的所須的資源,有可能與最後使用的資源有極大的差異。其原因在於,去高雄雖是一個明確的目的,但却缺乏足夠的資訊來說明此目的底下的各種可能路徑;不同的路徑自然隱含不同的成本(實際生活上我們也許只須一種路徑來支援你到達目的的,但系統不同,因為是要長久且大量的應付使用者的日常作業,所以每一種可能發生的路徑我們都須要實作。)。前一陣子有一則新聞說:有一位民眾透過 GPS 導航要去某一個地方,雖然 GPS 規劃出了一條不塞車的路徑,但却是一條人煙稀少的山路,結果那位民眾因汽車沒油(資源不足),而困在山裡,最後還要勞駕人民保母送汽油給他,才能脫離困境,顯然 GPS 沒有評估這種情形下所須的資源使用量。

 

       同樣的,新增客戶訂單或者管理客戶訂單,都是傳統上的功能列表,也是客戶很直覺提出的需求,如果我們以這樣的訊息加上一些些的瞭解來評估專案,往往會因沒有察覺在此需求底下的意圖、情況及限制條件的不同(使用者雖有以不同的方式來使用系統的自主性,但有時因為條件的不同,表面上相同的行為却已是不同的情況了),而錯估專案成本。誤解目標與意圖的意義是我們專案失敗的主因。目標有如海平上的冰山,明確清晰;意圖則是海平面底下的冰塊。據說讓鐵達尼號沉沒的不是海平面上的冰山而是海平面底下的冰塊,船長誤判了海平面下冰塊的威力,才是造成這場世紀大悲劇的主因。客戶需求就有如浮在海面上的冰山,在此需求底下的意圖、情況及限制條件則是海平面底下的冰塊,冰山底下的,才是我們要應付的危機,不容輕估。

UseCase 是描寫使用者使用系統某一項功能可能會採用那些方式的說明(注意:這裡所指的功能功能選單上的功能是不一樣的含義) ,每一種使用方式稱為一種情境或是一個場景,也可以說是我們前面所說的意圖、情況及限制條件。透過它可以協助我們去發掘與記錄使用者會以什麼樣不同的方式來使用系統,而系統又該以怎樣的方式來回應使用者。就如前面的例子:我們可以透過 UseCase 來分析使用者會以那幾種方式去新增客戶訂單,而您的系統又將如何針對不同的用法與條件採取相對的行動與使用者互動來協同完成工作。換包話說:「要系統能新增客戶訂單」是客戶需求,但為了完成這個客戶需求,您的系統須以好幾種不同的方法來協助使用者完成工作,這幾種方法就是不同的系統需求,我們就是透過使用案例來發掘與記錄系統需求。

    回顧一下過去您負責的專案,是不是經常被客戶抱怨,實現的系統常常與他們真正所要的有點誤差或不足以應付某些特殊情況。其原因就是沒有以比較充份的時間來探索使用者使用系統的各種可能方式,所造成的後果。傳統採用 DFD分析系統時,往往因太早使用技術性的觀點來處理客戶需求,急於解決問題,而忽略了使用者不同的意圖及各種限制因素;通過Use Case觀察系統,我們能夠將系統實現與系統目標分開,有助於瞭解最重要的部分――滿足用戶要求和期望,而不會沉浸於實現細節。必竟SA 的工作應該是找出對的事,然後再把事情做對。

    最後要再次說明的是:把使用案例的名稱看成是使用者對系統的一個要求期待,而系統在各種未知的意圖及條件因素底下,為了滿足使用者的這個要求期待所做的種種行為,則是透過使用案例的描述來記錄,結果是您將得到一組使用者在此要求下使用系統的各種可能情況的說明。UseCase 是目前發掘與記錄系統需求的好工具,協助我們以一種比較有系統有結構的方式來完成這項工作。

UML 裡各種圖形的使用時機

   從整體來看一個系統,系統有分靜態結構與動態行為二大構面。UML 提供的所有圖型,都是為了捕捉以及描述這二個構面。從建模的實際操作面來看,一個系統通常會因軟體發展生命週期的各個階段所要捕抓和描述的重點不同,而有不同的產出,這些產出可歸類為 UseCase View,Logical View,Component View   ,Process ViewDeployment View ,也就是所謂的四加一 觀點。每一個觀點可作為你製作 UML 各類圖型時思考的起點;另一方面又可作為你存放各類圖型的目錄。Rose 就拿它們來做為你建模時存放各階段所產的 UML 元素的目錄。Use Case View(使用案例觀點)一般又稱為功能觀點,通常一開始我們拿它來做為系統功能的說明,敘述使用者如何來使用系統,但它不會涉及如何建立系統的技術。雖然稱為使用案例觀點,但本目錄郤不是只能存放 Use Case Diagrams 的相關 UML 元素,他還是可以存放互動圖,活動圖,類別圖等 UML 元素,重點在於你想利用這些圖型來表達什麼樣的概念,如果是用來描述系統的功能並不涉及系統的實作技術,就該將它放在UseCase View 的觀點之下,管它是用 Use Case Diagram Class Diagram 或其它圖型。類別和動作實作出系統裡的使用案例,動作以互動圖和活動圖來詳加說明:如此,在系統功能觀點和動態觀點之間的連結就會存在。用在使用案類執行方面的類別,是以類別圖和狀態圖來描述  

狀態圖(State machine diagram/Statechar diagram)是描述系統行為時最常見的一種技術有助於描述某個物件橫跨幾個使用案例的行為
不過用它來描述幾個物件間的合作行為則不適合那是互動圖(interaction diagram)的責任。但也不要替每個類別畫出狀態圖,這種作法只是在浪費時間只用它來顯示內含某些有趣行為的類別或比較複雜而重要的類別,此時它可以幫助我們了解發生了什麼事情有些人特別用狀態圖來了解使用者介面與控制物件的某些行為
互動圖(interaction diagram)是用來描述數個物件在某個使用案例中的行為一般不會涉及特定的物件,只要點到高階流程就可以
活動圖(Activity diagram)適合用來展示數個物件在好幾個使用案例中的活動先後順序

互動圖與活動圖都是呈現物件間的訊息交流,因此當製作模型時,要使用那一種模型是依你當時想要展示那一方面的重點為考量
。到底是把發生在工作流程裡的一連串動作當成重點,還是把物件間的合作列為重點

Model-Driven Architecture 的開發流程

1.1 何謂MDA?

根據Standish Group 的調查顯示,在美國,專案失敗的因素中,有12.8%為使用者的資訊輸入不足,12.3%對於使用者需求及規格分析不完整,11.8% 起因於需求及規格的改變,這些近四成的失敗因素,都是在需求分析階段可以被避免及控制的,這也間接指出需求分析與管理在軟體開發的重要性。

看來SA 工作是一件繁雜又具挑戰性的工作,如能在一套有系統的方法下展開工作,應可節省不少時間與成本。MDA(Model-Driven Architecture)開發程序,講的是在開發過程將開發程序分為:

計算無關模型(Computation Independent Model;CIM)

對應的開發階段為「客戶需求分析」聚焦於業務系統及客戶需求,但不涉及系統的細節。

平台無關模型(Platform Independent Model;PIM)

對應的開發階段為「系統需求分析」聚焦於系統的行為,但不涉及與任何特殊技術平台(technology platform)的關係,如EJB,.NET或關聯性資料庫等

平台特定模型(Platform Specific Model;PSM)

對應的開發階段為「系統設計」,結合PIM所擬定的規格來顯示系統將如何在特殊技術平台進行設計,聚焦於系統落實於特定實體平台的技術細節。例如,SpringEJB2 .NET 都是一種實體平台。

實現相關模型(Implementation Specific Model, ISM)。

根據一組轉換規則,透過工具將PSM 轉換為可執行的應用系統,或是由人為遵循 PSM 編寫出程式碼。

                       <表一:MDA 說明>

系統分析師執行了前述的CIMPIM步驟,並且獲得高品質的產出之後,設計師會依據實作平台進一步產出PSM 階段的設計,並交由程式設計師按圖編碼,編寫出適用於特定實體平台的程式碼。本系統分析作業程序,將 CIM 階段分為五個步驟;PIM 階段分為九個步驟,每個步驟都是都以一個任務(Task)的形式呈現,以供所有系統分析人員參考。

這個流程指引框架並不是絶對的,每個專案應依它實際上的須要來進行調適

但如果試著依照這個流程指引去做,而不是毫無章法,就會離合理的流程更近一些。如果我們同意一致的標準流程,專案進度的測量工作就容易多了。另外需加以說明的是,流程與軟體發展生命週期並不是指同一件事。舉例來說,如果系統開發生命週期採” 瀑布式 (WaterFall) 開發,本指引的每一個步驟間的關係,都要在前一步驟完成與系統有關的作業後才能住下走,而且每一步驟在整個專案中,理論上只會執行一次。但如果是採 反覆 (Iteration)漸增 (Incremental) 的開發方式,則會以功能來區分,每個功能有如各自獨立的小型瀑布式 (WaterFall)專案,也就是本指引的每一步驟有時會在不同時期由不同功能所採用;有時是不同功能由不同開發小組在同一時期併行開發。

1.2 需求管理與系統分析發展流程圖

依據MDA,本發展指引所提及的步驟及產出,皆歸屬於 CIM PIM 階段,並未涉及PSM ISM 階段。 

   SA LoadMap                              <表二:SA Road Map>

各步驟對應的產出如下:

                         

                              

CIM-1:定義關鍵人員

產出關鍵人員清單。

CIM-2定義客戶需求

產出客戶需求表及非功能性需求表。

CIM-3:定義資料字典

產出 Glossary Term List資料字典列表及類別資料。

CIM-4:定義企業規則

產出企業規則列表。

CIM-5:分析業務流程

產出業務活動圖。

PIM-1:定義系統範圍

產出系統使用案例圖。

PIM-2:定義系統需求

產出系統使用案例敘述。

PIM-3:定義內外部介面

產出內外部介面表格。

PIM-4:分析領域模型

產出分析類別圖。

PIM-5分析系統流程

產出穩健圖。

PIM-6:分析使用者介面

產出使用者介面雛型資訊(包含雛型畫面及欄位規則說明)

PIM-7:定義系統測試規格

產出系統測試規格表及系統測試路徑分析圖。

PIM-8:定義系統操作模型

產出狀態圖。

PIM-9:定義功能架構圖

產出系統選單功能說明表格。

                                   <表三:各步驟產出對應表>

 

  根據這個流程,我們可以將 SRS 分成二部份,粉紅色步驟的產出資料,是可以直接拿來與第一線的使用者討論的,因為這幾個步驟的產出是使用者比較容易懂和可以接受的。黃色步驟的產出資料則比較屬於技術性的東西,可做為內部溝通與設計的基礎。當然如果有需要也是可以將所有步驟的產出資料都放進給使用者的 SRS 裡。

 

使用 Windows Live Writer 寫部落格用 Open Live Write 發佈至 Google Blogger 的方法

      Windows Live Writer(WLW) 是大部份部落客的最愛,因為它除了讓部落客可以很容易的所見即所得的離線編輯文章之外,它還可將內容發佈至各種不同的部落客系統,如:WordPress 或是 Blogger 之中。雖說 MS 自 2012 開始已不維護,但就算如此,憑藉著方便的使用性及眾多的外掛程式 ,仍然是部落客無可取代的工具之一。

    但如果您是使用 Google 的  Blogger,可以發現從 2015 年 5 月左右開始,使用  WLW 您已無法順利連上 Blogger 進行文章發佈。這個問題主因是 Blogger 更新了其  API  服務,登入 Google 帳號必須改用 OAuth 2.0。在 WLW 已不維護更新的情況下,我們已無法使用它來發佈內容至 Blogger 上了,這造成很多部落客的困擾。還好 2015/12 微軟宣佈將WLW轉為「開放原始碼專案」,讓Live Writer成為.NET Foundation的一員,並且將 WLW 更名為 Open Live Writer(OLW),目前除了是英文版外,使用介面幾乎跟 WLW 一模一樣,最重要的是它已支援 OAuth 2.0 新的認證方式,所以如果您使用 Google 的 Blogger 就可以改用  OLW 。

    不過因 OLW 才剛開放,所以它還沒有外掛程式可以用,這在某些方面真的是很不方便。例如在 WLW 裡,如果一位工程師想在文章裡加一些或寫一些  code,一般會使用所謂的  Code Snippet 方便編輯及樣式化程式碼,但在 OLW 裡目前則不容易達成。還好 WLW 與 OLW 本一家親,這二套軟體所支援的格式完全相容,如此就給了我們一個暫時的辦法,讓我們使用 WLW 來編輯文章,然後再透過 OLW 進行文章發佈。

     
為了方便的使用此方法,我們必須讓這二套軟體的草稿文章存在相同的路徑,如此才能方便的使用上述方法讓我們即可利用 WLW 眾的外掛程式,又可方便文章的編輯與排版,並讓文章順利的發佈至 Blogger。下面就以 Dropbox 存放位置為例,說明如何更改這二套軟體預設的草稿文章存放位置,讓二者指向相同的位置。

首先建立草稿文章儲放地
我們先在 Dropbox 底下新增個 My Webblog Posts 的資料夾,例如: C:\Dropbox\My Webblog Posts 做為 WLW 與 OLW 將來要同步的草稿文章儲存地。

接著,修改  WLW 的草稿文章路徑
       一般 WLW 預設的草稿文章是存放在目前使用者的 【我的文件】目錄下的 My Weblog Posts 目錄下,如果要修改這個預設儲存路徑,則必須要在使用者機碼(HKEY_CURRENT_USER\Softwre\Microsoft\Windows Live\Writer) 下新增一個 PostsDirectory 字串值,並填入新的路徑即可。

image

最後,修改  OLW 的草稿文章路徑
     其方法如同 WLW ,OLW 的使用者機碼如下:
HKEY_CURRENT_USER\Softwre\Microsoft\OpenLiveWriter

image

範例:
    例如我們要在文章裡展示一段價值千萬美元的程式碼,我們就可先透過  WLW 的外掛程式 Code Snippet插入程式碼,如下圖:

image

執行 Insert 後就會在文章內插入一段樣式化後的程式碼,感覺即美觀又專業。

   1: function Dollar(){

   2:      console.log("I am a rich man.");

   3: }

接著我們就可以將其存檔後開啟 OLW,然後從  【Open recent post】 中開啟此文章,如下圖:

image

image

    在 OLW 尚未釋出眾多外掛的過渡時期,此方法不失為一個簡便有效的作法。
參考文章:

如何將 Open Live Writer 的草稿文章自動同步到 Dropbox 雲端硬碟

2016年2月24日 星期三

JavaScript 原型式的物件導向繼承機制

在前一篇文章中我們提到唯有先搞清楚 JavaScript 中原型式的物件導向觀念與作法,才能在使用 JavaScript 這門語言時游刃有餘。但什麼是原型式的物件導向呢?
在大多數程式語言裡,每一個物件都是一個相關類別的實例(instance) ,這個類別提供了它所有實例所共用的程式碼。但在 JavaScript 裡是沒有類別這種東西的,取而代之是透過繼承其它物件來達到程式碼的共用。也就是說每個物件都會與其它的物件有關,這個關聯的物件就被稱為原型(雖然可以建立沒有原型的物件,但大部份而言,還是遵循上述規則)
以實字物件與內建建構式來說:
Var obj1 = new Object();
Var obj2 = {};

執行上述任一行程式,執行引擎會自動將 Object.prototype 設為新物件的原型
我們可以透過 ECMAScript  5 提供的 Object.getPrototypeOf 來查看這二個物件的原型:

console.log(Object.getPrototypeOf(obj1) === Object.prototype); //true
console.log(Object.getPrototypeOf(obj2) === Object.prototype); //true

也就是說不管使用實字物件方法或內建建構式中的任一種方法來建立新物件,新物件的原型一律是 Object.prototype,這會產生一種現象,當我們動態為任一物件的原型新增一個屬性或方法時,也會直接影影子到其它透過實字物件或內建建構式建立出來的物件,如下範例:

var obj1 = {};       //實字物件
           var obj2= new Object(); //內建建構式
           //動態透過 obj 物件在其原型上新增一個  say 方法
        obj1.constructor.prototype.say=function()  //constructor 後面在說明
          {
                alert('I am a prototype method');
          };
          obj1.say();    //output I am a prototype method
          obj2.say();    //I am a prototype method

 由以上的結果可以看出二個現象:
1.  在物件建立之後,再動態的在其原型物件上新增屬性或方法,仍然有效。
2. 原型上的屬性或方法是透過附加的方式,加到新物件上並非是採複製的方式,所以就算只修改任一物件的原型上的方法,也能立即反應在其它物件上,表示它們確實是共用一份程式碼,它們的關係如下:

  

  

,這個 Object prototype   JavaScript 所有物件之母

如果我們是透過自訂建構式函式建立新的物件又如何呢?

    function  Dog(name){
         this.name;
};

Dog.prototype.getName = function()[
     return this.name;
};

var dog = new Dog(‘harry’);
console.log(Object.getPrototypeOf(dog) ===Dog.prototype); //true
Dog 建構函式內建了一個預設的 prototype 屬性含有一個  
物件,它一 開始大致上是空的,它就是所謂的  dog 物件的   
原型,在上面的範例中,我們新增了一個方法到 
Dog.prototype 物件中:getName。當我們使用 new 建立了 Dog 
的一個實例時, dog 物件的原型就自動被設為儲存在 
Dog.prototype 中的物件,下圖顯示了它們的關係:
     
               

它一樣遵循著在物件建立之後,再動態的在其原型物件上新增屬性或方法,對已建立之物件仍然有效及原型上的屬性或方法是透過附加的方式,加到新物件上並非是採複製的方式,這二項規則,下列程式碼可以證明:


var Dog = function(name){
         this.name = "marry";
    };

    Dog.prototype.getName = function(){     
         return this.name;
    };
          
    var obj01 = new Dog("harry");
    var obj02 = new Dog("marry");
          
//在物件建立後才去修改原型裡的方法
    Dog.prototype.getName = function(){
   
     return  "harry" +"   "+"marry";
    }
console.log(obj01.getName()); // harry” +”   “+”marry”
console.log(obj02.getName());//“harry” +”   “+”marry”

二個新物件的 getName 方法都是輸出 “harry” +”   “+”marry”
這個特點和 Java C# 這種  class-base   OOPL 有很大的不同,也是 javaScript 最大的特點。因為在傳統的物件導向系統裡,我們是無法在物件產生之後再去修改類別並讓已建立的物件能立即發揮作用的。

也許我們又會追問,那函式預設的原型即然也是一個物件,按照定義,在 JavaScript 裡物件都有個原型,那這個函式的原型物件的原型又是什麼?透過下列實驗我們可以看出,Object.prototype 就是函式的原型物件的原型:

alert(Object.getPrototypeOf(Dog.prototype) === Object.prototype); //true

或者透過下列程式來驗證:
var Dog = function(name){
         this.name = name;
    };

    Dog.prototype.getName = function(){   
        return this.name;
    };
       
        var Cat = function(name){
         this.name = name;
    };
       
        Cat.prototype.getName = function(){    
         return this.name;
    };
       
       
    var obj01 = new Dog("I am dog");
    var obj02 = new Cat("I am cat");
       
        Object.getPrototypeOf(Dog.prototype).getdis = function(){
           alert('I am Object.prototype');
        }
         
       
        obj01.getdis(); //'I am Object.prototyp
    obj02.getdis();//'I am Object.prototyp

JavaScript 所有物件的原型基本上都可以追溯到這個物件,Object.prototype JavaScript 裡的萬物之母(基本上,在 JavaScript 裡除了這個物件沒有原型外,其它的物件都有原型)。這種一層一層往上委託的機制就是 JavaScript 裡所謂的物件的原型鏈,當我們需要存取任一物件的屬性或方法時,物件會先在本身定義的屬性裡尋找,如果沒有找到就往其原型裡找,如果還沒找到就再往其原型的原型裡找,直到找到最頂端,也就是  Object.prototype,如果都沒找到,就返回 undefined

至此我們可以稍微整理一下幾個重要的事實:
1. JavaScript 裡的所有函式都有一個 prototype 屬性,它存放一個稍為原型的物件。
2. JavaScript 的每個物件都擁有一個名為 constructor 的隱性屬性,指向當初用來建構該物件的建構式並且由於 prototype 原型屬性存在於建構式裡,所以我們可得到如下的關係圖:
    
    


  
  一個物件的原型除了可透過dog.constructor.prototype 取得外,也可利用ES5 提供 getPrototypeOf 方法取得,另外在某些瀏覽器裡,如 chrom   firefox ie9 以上,也為所有物件提供了一個 __proto__ 的屬性,當物件被建立時,這個 __proto__ 屬性的值就是它的構造函數的 prototype ,所以

   Object. getPrototypeOf(dog) === dog.constructor.prototype === dog.__proto__      === Dog.prototype
另外,一個物件如果己建立,緃使我們不知它原來的建構式為何?我們仍能透過 dog.constructor 來得知它原來的建構式是什麼,甚至透過它建立另一個實例,如下:
var dog2 = dog.constructor();


   prototype JavaScript 裡是如此的重要,以致於有那麼多種方式可以去存取到它, prototype 屬性類似於  class-base 等語言中的Class 做為物件的藍圖的角色,是實作 OOP 中繼承的機制 ,先了解這種基於原型的繼承機制我們才能繼續探索 JavaScript 中的封裝、多型及使用  JavaScript 特有原型物件導向機制來實作各種設計模式。