javascript
理解JavaScript中的原型继承(2)
兩年前在我學(xué)習(xí)JavaScript的時(shí)候我就寫(xiě)過(guò)兩篇關(guān)于原型繼承的博客:
理解JavaScript中原型繼承
JavaScript中的原型繼承
這兩篇博客講的都是原型的使用,其中一篇還有我學(xué)習(xí)時(shí)的錯(cuò)誤理解。今天看《Understanding Scopes》這讓我從新思考了一下原型繼承,更重要的是站在一個(gè)繼承設(shè)計(jì)者的角度再看一下原型繼承。
在傳統(tǒng)的面向類的繼承體系中,我們有個(gè)Best Practices是優(yōu)先使用(對(duì)象)組合代替(類)繼承,而原型繼承是這個(gè)思想的一個(gè)運(yùn)用。和面向?qū)ο蠛秃瘮?shù)式編程一樣,使用幾乎任何語(yǔ)言都可以實(shí)現(xiàn)這樣的思想,我以前學(xué)的只是這個(gè)思想的一個(gè)JavaScript實(shí)現(xiàn),而已。
基于原型的繼承其實(shí)是一種組合式的繼承,樸素的說(shuō)法就是子域中屬性找不到的話就去父域中找找,這里的父域是用原型(__proto__)去引用的,依次遞歸整個(gè)原型鏈。最終的實(shí)現(xiàn)其實(shí)就是對(duì)象的組合。子對(duì)象包含父對(duì)象的引用。既然是繼承必然涉及到重名問(wèn)題,子對(duì)象和父對(duì)象各自相當(dāng)于一個(gè)作用域,重名問(wèn)題的處理也是就近(可覆蓋shadow/隱藏hide)原則,即子作用域的同名屬性會(huì)起作用,隱藏了父作用域的同名屬性,但是由于是組合,這兩個(gè)屬性是獨(dú)立的。我們用偽代碼看看:
aParent = {name:’jerry’}
aChild = {__proto__:aParent, name:’frank’}
aChild中的name和aParent中的name是各自獨(dú)立的。我們aChild.name=’unknown’并不會(huì)改變aParent.name。
?
有一點(diǎn)要拿出單獨(dú)說(shuō)說(shuō),造成迷糊的最大根源就是誤解,對(duì)于如下代碼:
aParent = {name:’jerry’}
aChild = {__proto__:aParent}
若我們?nèi)Child.name的值,我們很容易resolve,那就是子域中找不到,去父域中找,找到了jerry。但是對(duì)于:aChild.name = ‘frank’這樣的賦值代碼我們會(huì)產(chǎn)生歧義(ambiguous),我們可能有兩中含義:
1,更新父域中的name屬性為frank。
2,設(shè)置子域中的name屬性為frank。
JavaScript選用的方式是第2種。即設(shè)置(新建)子域自己的name屬性為frank,并隱藏了父域中的name屬性。我們通常誤以為JavaScript是按1的方式工作,其實(shí)不是。
?
另外類(模版)其實(shí)在編程語(yǔ)言的實(shí)現(xiàn)中是可有可無(wú)的,像JavaScript壓根就沒(méi)有類(模版),他只有對(duì)象,new Point()只不過(guò)是一個(gè)語(yǔ)法糖,跟aObj = createObject()是一樣的,只是調(diào)用一個(gè)方法去生成一個(gè)對(duì)象,而已。
轉(zhuǎn)載于:https://www.cnblogs.com/Jerry-Chou/p/understanding-prototype-inheritance-2.html
總結(jié)
以上是生活随笔為你收集整理的理解JavaScript中的原型继承(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 分期乐放款额度不足什么意思?是什么原因?
- 下一篇: 修改wordpress上传文件大小限制