物件原型- 學習該如何開發Web | MDN
文章推薦指數: 80 %
JavaScript 的物件即透過原型(Prototype) 機制相互繼承功能,且與典型的物件導向(OO) 程式語言相較,其運作方式有所差異。
我們將透過本文說明相異之 ...
SkiptomaincontentSkiptosearchSkiptoselectlanguage學習該如何開發WebJavaScript—動態的客戶端指令JavaScript物件介紹物件原型ArticleActions正體中文(繁體)ThispagewastranslatedfromEnglishbythecommunity.LearnmoreandjointheMDNWebDocscommunity.「原型」架構的程式語言?了解原型物件原型屬性也定義所要繼承的成員再次溫習create()建構子的屬性修改原型摘要RelatedTopics
全新手請從這開始!
Web入門
Web概述
安裝基本軟體
自己的網站會是什麼樣子?
處理檔案
HTML基礎概念
CSS基礎概念
JavaScript基礎概念
發佈自己的網站
Web運作的方式
HTML—架構Web
HTML介紹
HTML概述
HTML入門
標題裡是什麼?HTML中的後設資料(Metadata)
HTML文字基礎概念
建立超連結
進階文字格式
文件與網站架構
HTML除錯
親和度:設個字母
親和度:架構出具備內容的網頁
多媒體與嵌入
多媒體與嵌入的概述
HTML中的圖片
視訊與音訊內容
從物件到iframe—其他嵌入技巧
為Web新增向量圖
適應性圖片
親和度:Mozilla形象頁面
HTML表格
HTML表格概述
HTML表格基礎
HTMLtableadvancedfeaturesandaccessibility
Assessment:Structuringplanetdata
CSS—設計Web的風格
初探CSS
初探CSS(概述)
CSS是什麼?
CSS入門
HowCSSisstructured
CSS怎麼運作
Assessment:Stylingabiographypage
CSS組件
CSSbuildingblocksoverview
Cascadeandinheritance
CSSselectors
Theboxmodel
Backgroundsandborders
Handlingdifferenttextdirections
Overflowingcontent
CSSvaluesandunits
SizingitemsinCSS
Images,media,andformelements
Stylingtables
DebuggingCSS
OrganizingyourCSS
Assessment:FundamentalCSScomprehension
Assessment:Creatingfancyletterheadedpaper
Assessment:Acool-lookingbox
樣式化文字
樣式化文字概述
基礎的文字與字型樣式化
樣式化列表
樣式化連結
Web字型
親合度:設定社區大學首頁的版面
CSS版面配置
CSS版面配置概述
IntroductiontoCSSlayout
NormalFlow
彈性區塊
格線
浮動
定位
Multiple-columnlayout
Responsivedesign
Beginner'sguidetomediaqueries
Legacylayoutmethods
Supportingolderbrowsers
Assessment:Fundamentallayoutcomprehension
JavaScript—動態的用戶端指令
JavaScript第一步
JavaScript第一步概述
什麼是JavaScript?
初次接觸JavaScript
出了什麼問題?JavaScript疑難排解
儲存你所需的資訊—變數
JavaScript基礎概念—數字與運算子
處理文字—JavaScript中的字串
有用的字串函式
陣列
親合度:傻瓜故事產生器
JavaScript基礎要件
JavaScript基礎要件概述
於程式碼中決策—條件
程式碼迴圈
函式—可重複使用的程式碼區塊
建立自己的函式
函式回傳值
事件介紹
親合度:圖庫
JavaScript物件介紹
JavaScript物件概述
物件基礎概念
物件原型
Object-orientedprogrammingconcepts
ClassesinJavaScript
使用JSON資料
物件建構實作
親合度:為彈跳球展示新增功能
非同步的JavaScript
AsynchronousJavaScriptoverview
IntroducingasynchronousJavaScript
Howtousepromises
Implementingapromise-basedAPI
Introducingworkers
Assessment:sequencinganimations
客戶端webAPIs
客戶端webAPIs
IntroductiontowebAPIs
文件操作
Fetchingdatafromtheserver
ThirdpartyAPIs
Drawinggraphics
VideoandaudioAPIs
Client-sidestorage
網頁表單-與使用者資料合作
核心的表單學習途徑
網頁表單概述
Yourfirstform
如何建構網頁表單
Basicnativeformcontrols
TheHTML5inputtypes
Otherformcontrols
Stylingwebforms
Advancedformstyling
UIpseudo-classes
Client-sideformvalidation
Sendingformdata
深入網頁表單
Howtobuildcustomformcontrols
SendingformsthroughJavaScript
CSSpropertycompatibilitytableforformcontrols
無障礙網頁—每個人都可以使用的網頁
無障礙網頁指南
無障礙網頁概述
何謂無障礙網頁?
HTML:Agoodbasisforaccessibility
CSSandJavaScriptaccessibilitybestpractices
WAI-ARIA基礎
Accessiblemultimedia
行動裝置上的無障礙
無障礙網頁評估
Assessment:Accessibilitytroubleshooting
工具與測試
Client-sidewebdevelopmenttools
Client-sidewebdevelopmenttoolsindex
Client-sidetoolingoverview
Commandlinecrashcourse
Packagemanagementbasics
Introducingacompletetoolchain
Deployingourapp
介紹前端框架
前端框架簡介
Frameworkmainfeatures
React
GettingstartedwithReact
BeginningourReacttodolist
ComponentizingourReactapp
Reactinteractivity:Eventsandstate
Reactinteractivity:Editing,filtering,conditionalrendering
AccessibilityinReact
Reactresources
Ember
GettingstartedwithEmber
Emberappstructureandcomponentization
Emberinteractivity:Events,classesandstate
EmberInteractivity:Footerfunctionality,conditionalrendering
RoutinginEmber
Emberresourcesandtroubleshooting
Vue
開始學Vue
CreatingourfirstVuecomponent
RenderingalistofVuecomponents
Addinganewtodoform:Vueevents,methods,andmodels
StylingVuecomponentswithCSS
UsingVuecomputedproperties
Vueconditionalrendering:editingexistingtodos
FocusmanagementwithVuerefs
Vueresources
Svelte
Svelte入門
StartingourSvelteTodolistapp
DynamicbehaviorinSvelte:workingwithvariablesandprops
ComponentizingourSvelteapp
AdvancedSvelte:Reactivity,lifecycle,accessibility
WorkingwithSveltestores
TypeScriptsupportinSvelte
Deploymentandnextsteps
Angular
Angular新手入門
開始開發我們的Angular待辦事項應用程式
使用樣式點綴我們的Angular應用程式
建立一個item元件
篩選我們的待辦事項項目
建構Angular應用程式與更多資源
GitandGitHub
GitandGitHub概述
HelloWorld
GitHandbook
ForkingProjects
Aboutpullrequests
MasteringIssues
跨瀏覽器測試
跨瀏覽器測試概述
跨瀏覽器測試介紹
測試執行策略
處理常見的HTML與CSS問題
處理常見的JavaScript問題
處理常見的親合度問題
建置功能偵測
自動化測試介紹
設定自己的自動化測試環境
伺服端網站程式設計
第一步
第一步概述
伺服端介紹
用戶端概述
伺服端網路框架
網站安全
Django網站框架(Python)
Django網站框架(Python)概述
介紹
設定開發環境
線上教學:本地圖書館網站
線上教學2:建立網站骨架
線上教學3:使用模型
線上教學4:Django管理網站
線上教學5:建立我們的首頁
線上教學6:泛型清單與細節檢視
線上教學7:會話(Sessions)框架
線上教學8:使用者授權與許可
線上教學9:搭配表單
線上教學10:測試Django的WebApp
線上教學11:佈署Django至產品
WebApp安全性
親合度:DIY迷你部落格
Express網站框架(node.js/JavaScript)
Express網站框架(Node.js/JavaScript)概述
Express/Node介紹
設定Node(Express)的開發環境
Express教學1:本地圖書館網站
Express教學2:建立骨架網站
Express教學3:使用資料庫(Mongoose)
Express教學4:路由與控制器
Express教程5:呈現圖書館的資料
Express教學6:使用表單
Express教學7:佈署到正式環境
更多資源
常見問題
HTML問題
CSS問題
JavaScriptquestions
Web的運作方式
工具與設定
設計與親合度
「原型」架構的程式語言?了解原型物件原型屬性也定義所要繼承的成員再次溫習create()建構子的屬性修改原型摘要物件原型
前頁
Overview:Objects
次頁
JavaScript的物件即透過原型(Prototype)機制相互繼承功能,且與典型的物件導向(OO)程式語言相較,其運作方式有所差異。
我們將透過本文說明相異之處、解釋原型鍊(Prototypechain)運作的方式,並了解原型屬性是如何將函式新增至現有的建構子(Constructor)之中。
必備條件:
基本的電腦素養、已初步了解HTML與CSS、熟悉JavaScript(參閱〈Firststeps〉與〈Buildingblocks〉以及OOJS基礎概念(參閱〈Introductiontoobjects〉。
主旨:
了解JavaScript的物件原型、原型鍊的運作方式、應如何將新的函式加入原型屬性之中。
「原型」架構的程式語言?常有人說JavaScript是原型架構的程式語言—各個物件均具備1組原型物件作為範本物件,用以繼承函式與屬性。
物件的原型物件可能也具備原型物件,並繼承了其上的函式與屬性。
這就是我們所謂的「原型鍊(Prototypechain)」,同時正好說明為何A物件的屬性與函式是透過B物件的屬性與函式所定義。
精確點說,這些屬性與函式都是透過物件的建構子函式所定義,並非物件實例本身。
傳統的OOP都是先定義了類別,接著在建立物件實例之後,在類型上定義的所有屬性與函式均複製到此實例。
但JavaScript不會複製這些屬性與函式,卻是在物件實例與其建構子之間設定連結(原型鍊中的連結),只要順著原型鍊就能在建構子之中找到屬性與函式。
先看個範例會比較清楚點。
了解原型物件先回到我們寫過的Person()建構子範例。
在你的瀏覽器裡載入範例。
如果你還沒看完前篇文章並製作出此範例,可先使用oojs-class-further-exercises.html這個範例(可看到原始碼)。
我們在此範例中定義了建構子函式:
functionPerson(first,last,age,gender,interests){
//propertyandmethoddefinitions
};
接著建立如下的物件實例:
varperson1=newPerson('Bob','Smith',32,'male',['music','skiing']);
如果你在自己的JavaScript主控台中鍵入「person1.」,應該會看到瀏覽器根據此物件可用的成員名稱開始自動補完:
在此列表中,可以看到person1原型物件上所定義的成員,也就是Person()建構子—name、age、gender、interests、bio、greeting。
你也會看到其他如watch、valueOf等,同樣也是定義在Person()建構子原型物件之上的成員,如此構成Object。
下圖顯示原型鍊的運作方式。
所以當你在person1上呼叫了「實際上是定義於 Object上的函式」,會發生什麼事呢?舉例來說:
person1.valueOf()
此函式僅回傳所呼叫的物件數值。
此範例所將發生的是:
瀏覽器先檢查person1物件上是否有可用的valueOf()函式。
其實沒有,所以瀏覽器接著檢查person1物件的原型物件(Person)上是否有可用的valueOf()函式。
同樣沒有,所以瀏覽器再檢查Person()建構子的原型物件(Object)上是否有可用的valueOf()函式。
這次有,所以就會呼叫。
注意:再次重申,在原型鍊中的函式與屬性並不是從任一物件複製到另一個物件,而是如上述的,沿著該原型鍊向上存取而得。
注意:直接存取物件的原型物件,並沒有一定的方式。
原型鍊中,項目之間的「連結」均定義於內部屬性之內,即JavaScript規格中的[[prototype]](可參閱ECMAScript)。
新版瀏覽器均具備所謂的「__proto__(兩邊都是2個底線)」屬性,其中就包含了物件的原型物件。
舉例來說,你可嘗試「person1.__proto__」與「person1.__proto__.__proto__」看看程式碼中的鍊會是什麼樣子!
原型屬性也定義所要繼承的成員所以該在哪裡定義所要繼承的屬性與函式呢?若看一下Object參考頁面,你就會看到左邊列出許多屬性與函式,遠超過上方擷圖所列person1物件所繼承的成員數量。
有些繼承了,有些則無?為什麼呢?
原因在於,繼承的成員就是在prototype屬性(你也能稱之為子命名空間subnamespace)中定義的成員,也就是以「Object.prototype.」開頭的成員;並非只以「Object.」開頭的成員。
prototype屬性值就是1個物件,基本上儲存了許多我們想「讓原型鍊上的物件一路繼承下去」的屬性與函式。
所以如Object.prototype.watch()、Object.prototype.valueOf()等等,均可用於繼承自Object()的任何物件類型,包含以建構子建立的新物件實例。
Object.is()、Object.keys(),及其他未於prototype內定義的成員,也就不會繼承至1).物件實例或2).從Object()繼承而來的物件類型。
這些函式\屬性都只能用於Object()建構子本身。
注意:這看起來很奇怪:你怎麼能在建構子上定義函式(Method),而且這建構子本身也是函式(Function)?其實「Function」也屬於一個物件類型,可參閱Function()建構子參考以進一步了解。
你可自行檢查現有的原型屬性。
回到我們之前的範例,試著於JavaScript主控台中輸入:
Person.prototype
輸出結果很平淡,畢竟我們並未在自定的建構子原型上定義任何東西。
依預設值,建構子的prototype都是從空白開始。
現在可嘗試下列:
Object.prototype
這樣就會看到Object的prototype屬性中所定義的許多函式,而繼承自Object的物件也能找到這些函式。
只要試著尋找如String、Date、Number、Array等全域物件的原型上定義的函式與屬性,就會看到JavaScript中的其他原型鍊繼承範例。
這些物件都在其原型上定義了多個成員,因此可作為你建立字串時的範例:
varmyString='Thisismystring.';
myString上立刻就有多個有用的函式,如split()、indexOf()、replace()等。
重要:prototype這個屬性,是JavaScript中最讓人混淆的名稱之一。
你可能會認為this屬性即指目前物件(currentobject)的原型物件(prototypeobject),但它其實不是原型(應該是可透過__proto__存取的內部物件(internalobject)才對,記得上面說過的嗎?)。
prototype是一個物件(object),內含了你定義所應該繼承的成員。
再次溫習create()我們先前講過用Object.create()函式建立新物件實例的方法。
舉例來說,你可先在前面的JavaScript主控台範例中試著輸入:
varperson2=Object.create(person1);
create()實際上是透過特定的原型物件,來建立新的物件。
我們在這裡將person1作為原型物件,建立了person2。
你可於主控台輸入下列以測試之:
person2.__proto__
如此將回傳person1物件。
建構子的屬性每個物件實例都具備1個建構子屬性,指向「用以建立實例」的原始建構子函式。
舉例來說,若在主控台中輸入下列指令:
person1.constructor
person2.constructor
應該兩者都會回傳Person()建構子,因為此建構子包含這些實例的原始定義。
偷吃步的方法,是將圓括弧加到constructor屬性(須包含任何必要參數)末端,以從該建構子建立其他物件實例。
畢竟建構子也是函式(Function),所以可透過圓括弧將之觸發。
你只要納入new這個關鍵字,即可將此函式作為建構子。
在主控台中輸入:
varperson3=newperson1.constructor('Karen','Stephenson',26,'female',['playingdrums','mountainclimbing']);
現在可試著存取新物件的功能,例如:
person3.name.first
person3.age
person3.bio()
這樣運作得還不差。
你不需常常用這方法,但當你要建立新的實例,又因為某些原因找不到原始建構子的參照,這就特別有用了。
此外,constructor屬性還有其他用處。
舉例來說,如果你有個物件實例,並要回傳建構子(本身就是實例)的名稱,就透過:
instanceName.constructor.name
也可嘗試:
person1.constructor.name修改原型先看看建構子的prototype屬性的修改範例:
回到oojs-class-further-exercises.html範例,先在本機儲存1份原始碼的副本。
在現成的JavaScript中加入下列程式碼,即是將新函式新增到建構子的prototype屬性:
Person.prototype.farewell=function(){
alert(this.name.first+'hasleftthebuilding.Byefornow!');
}
儲存程式碼並在瀏覽器中載入頁面,再輸入下列程式碼:
person1.farewell();
這時應該會看到警示訊息且內含了建構子所定義的人名。
這樣很有用,但如果能動態更新整個繼承鍊,且從建構子分割出來的所有物件實例都能使用此新的函式,就會更有用!
花個1分鐘想想,我們的程式碼中定義了建構子,然後根據建構子建立實例物件,接著將新函式添增到建構子的原型:
functionPerson(first,last,age,gender,interests){
//propertyandmethoddefinitions
};
varperson1=newPerson('Tammi','Smith',32,'neutral',['music','skiing','kickboxing']);
Person.prototype.farewell=function(){
alert(this.name.first+'hasleftthebuilding.Byefornow!');
}
但是farewell()函式仍可用於person1物件實例,其可用的功能已自動更新過。
如此證明了我們之前對原型鍊的說明,也代表瀏覽器會沿著鍊往上找「尚未於物件實例上定義的函式」,而非「複製到實例中的函式」。
如此可建構強大且靈活的系統。
注意:如果你在讓此範例運作時感覺有點困難,可參閱oojs-class-prototype.html範例(也可看即時運作的情形)。
你很少會看到在prototype屬性上定義的屬性,因為照此範例定義的屬性彈性較低,舉例來說,你可新增如下的屬性:
Person.prototype.fullName='BobSmith';
但因為幾乎不會有人取這名字,所以就沒什麼彈性。
最好可以在name.first與name.last之外建立fullName:
Person.prototype.fullName=this.name.first+''+this.name.last;
但因為這樣會參照全域範圍,而非函式範圍,所以也不適用。
若呼叫此屬性,則將回傳undefinedundefined。
這種模式適合我們先前於原型中定義的函式,因為該函式就是在功能範圍之內,且可成功轉移至物件實例的的範圍。
因此你可能會在原型中定義常數屬性(也就是永遠不需更改的屬性),但一般來說會比較適合在建構子中定義屬性。
事實上,許多物件定義較常見的模式,就是在建構子中定義屬性,而在原型中定義函式。
這樣一來,建構子只有屬性定義;函式則切分到不同的區塊,讓整個程式碼較清楚易讀。
舉例來說:
//Constructorwithpropertydefinitions
functionTest(a,b,c,d){
//propertydefinitions
};
//Firstmethoddefinition
Test.prototype.x=function(){...}
//Secondmethoddefinition
Test.prototype.y=function(){...}
//etc.
你可在PiotrZalewa的「schoolplanapp」範例中看到實際運作的範例。
摘要本文說明了JavaScript物件原型,包含原型物件鍊是如何讓物件能互相繼承其特性、原型屬性的本質、原型屬性又是如何能將函式新增至建構子,以及其他相關概念。
接著我們將讓你在自己的任2個自訂物件之間,實作功能的繼承。
前頁
Overview:Objects
次頁
Foundaproblemwiththispage?EditonGitHubSourceonGitHubReportaproblemwiththiscontentonGitHubWanttofixtheproblemyourself?SeeourContributionguide.Lastmodified:2022年6月23日,byMDNcontributors
延伸文章資訊
- 1想寫程式創業?先搞懂什麼是Prototype! - 全民Coding
Prototype 泛指一個產品的初步樣子,至於如何定義「初步的樣子」,其實沒有明確規範,有時已經很接近成品,有時只有樣子但是功能很少,有時功能滿完整但是 ...
- 2prototype - 雛型 - 國家教育研究院雙語詞彙
出處/學術領域, 英文詞彙, 中文詞彙. 學術名詞 視覺藝術名詞, prototype, 原型. 學術名詞 圖書館學與資訊科學名詞, prototype, 原型. 學術名詞
- 3prototype中文(繁體)翻譯:劍橋詞典
prototype的例句. prototype. The ability to distinguish between prototypes and exceptions helps to de...
- 4設計師必懂(一) - Wireframe 與Prototype 的不同 - 設計大舌頭
原型(Prototype) ... 原型與線框稿不同的地方在於,原型是屬於中到高度擬真來呈現最終使用者介面的方法。運用原型的目的即是模擬使用者與介面之間的互動,例如說按鈕按下後會 ...
- 5prototype - Yahoo奇摩字典搜尋結果
prototype. KK[ˋprotə͵taɪp]; DJ[ˋprəutətaip]. 美式. n. 原型;標準;模範. Dr.eye 譯典通 · prototype · 查看更多. IPA[...