原型、原型对象、构造函数、原型链理解
1. 基本概念:
“原型屬性”也可以叫做“原型”(prototype):所有函數(shù)都有prototype,我覺得可以理解為python中的類屬性,不需要通過實(shí)例,直接用類(es5就是函數(shù)名)可以調(diào)用,下面列舉了三種創(chuàng)建函數(shù)的方法,函數(shù)創(chuàng)建后都有prototype屬性,prototype指向“原型對(duì)象”。
// 函數(shù)聲明 function F1() { }; // 表達(dá)式定義 let F2 = function () { }; // 函數(shù)構(gòu)造 let F3 = new Function('n1', 'n2', 'return n1+n2');console.info(F1.prototype) //F1 {} console.info(F2.prototype) //F2 {} console.info(F3.prototype) //anonymous {}?
原型對(duì)象(prototype所指向的對(duì)象):這玩意主要就是用來繼承用的,包含實(shí)例的方法和屬性。說白了也就是一個(gè)對(duì)象,用來定義函數(shù)對(duì)象的屬性、方法,默認(rèn)情況下它包含一個(gè)constructor屬性,如果你重新定義可以覆蓋constructor屬性。
原型對(duì)象與構(gòu)造函數(shù)配合一起,就形成一個(gè)類了,然后構(gòu)造函數(shù)接收每次初始化對(duì)象的初始值,原型對(duì)象就提供類模板。而在其他java、python中都寫在class中,當(dāng)然es6也加入了class;以下的簡單代碼幫助理解上面說的,定義一個(gè)動(dòng)物類,根據(jù)構(gòu)造函數(shù)創(chuàng)造不同的動(dòng)物,如果需要?jiǎng)?chuàng)建特殊動(dòng)物,可以繼承然后添加一些特殊屬性、方法再創(chuàng)建。---------總結(jié)es5的類可以用“構(gòu)造函數(shù)+構(gòu)造函數(shù)的prototype”來定義,類的對(duì)象使用“new構(gòu)造函數(shù)”來生成。
// 構(gòu)造函數(shù) let Animal = function (name) {this.name = name } // 原型對(duì)象定義 Animal.prototype.getAnimal = function () {return this.name } // 創(chuàng)建對(duì)象,會(huì)繼承Animal.prototype let dog = new Animal('dog') let cat = new Animal('cat') console.info(dog.getAnimal()) console.info(cat.getAnimal())?
?
上圖展示了構(gòu)造函數(shù)、原型對(duì)象、具體對(duì)象的屬性、方法及屬性值。
?
普通對(duì)象與函數(shù)對(duì)象:通過函數(shù)對(duì)象 new一下可以得到普通對(duì)象,把函數(shù)對(duì)象理解為類,普通對(duì)象為實(shí)例。如下代碼加強(qiáng)理解,可以看到函數(shù)對(duì)象new完以后生產(chǎn)的對(duì)象是object;函數(shù)對(duì)象中都有prototype前面已經(jīng)說過了(為什么函數(shù)對(duì)象中會(huì)有這個(gè)屬性以后讀取更深以后再解答)
// Animal函數(shù)對(duì)象 let Animal = function (name) {this.name = name } // 原型對(duì)象 Animal.prototype.getAnimal = function () {return this.name } // 通過函數(shù)對(duì)象創(chuàng)建普通對(duì)象 let dog = new Animal('dog') console.info(typeof dog) //object總結(jié): 函數(shù)對(duì)象通過new Function()可以得到,Function對(duì)象可以構(gòu)造函數(shù)對(duì)象。而函數(shù)對(duì)象又可以new一個(gè)普通對(duì)象出來。
?
__proto__:所有對(duì)象都有__proto__這個(gè)屬性,這個(gè)屬性指向?qū)?yīng)“函數(shù)對(duì)象(就理解為類)”的prototype,這也是實(shí)現(xiàn)原型鏈的根本,在書中一般都用[[prototype]]。
?
構(gòu)造函數(shù)和constructor屬性:其實(shí)前面的圖已經(jīng)標(biāo)注了,概念后續(xù)補(bǔ)上。
?
原型鏈:ES中的繼承主要用原型鏈來實(shí)現(xiàn),記住了這玩意主要用來實(shí)現(xiàn)繼承。其基本思想是:利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法(js高級(jí)程序設(shè)計(jì)說的),還是用以上的例子來說明
let Animal = function (name) {this.name = name } // 原型對(duì)象定義 Animal.prototype.getAnimal = function () {return this.name } // 創(chuàng)建對(duì)象,會(huì)繼承Animal.prototype let dog = new Animal('dog') let cat = new Animal('cat') console.info(dog.valueOf()) console.info(cat.valueOf())跟上面例子就差了最后console打印部分,我們定義的Animal沒有寫valueof()為什么可以調(diào)用這個(gè)方法呢?到底是什么鬼?這就是原型鏈搞的鬼。我再把上面的圖形完善一下
上圖還有兩個(gè)屬性的指向沒有畫,第一、Animal的__proto__指向;第二、Animal.prototype的__proto__指向。
這個(gè)圖把Animal.prototype的__proto__指向添加了,
圖形說明:
1. Animal.prototype是個(gè)普通對(duì)象,ES中Object是所有對(duì)象的基礎(chǔ)。所有引用類型都繼承了Object;所有函數(shù)的默認(rèn)原型是都Object的實(shí)例,因此Animal.prototype的__proto__指向Object.prototype,這個(gè)一定要理解。
2. 我們調(diào)用cat.valueOf()解釋器會(huì)先找dog實(shí)例中有沒有這個(gè)方法,沒有就在Animal.prototype中查找,沒有再去Object.prototype中查找。然后就有了cat.valueOf()的運(yùn)行結(jié)果:Animal { name: 'cat' }。
3. Object構(gòu)造函數(shù)的prototype也指向Object.prototype。
?
最后把Animal的__proto__指向補(bǔ)完基本就差不多了。
?
轉(zhuǎn)載于:https://www.cnblogs.com/caoyi/p/10166831.html
總結(jié)
以上是生活随笔為你收集整理的原型、原型对象、构造函数、原型链理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5.6 定义模型
- 下一篇: 个人作业——软件工程实践总结