摘要:原型鏈?zhǔn)紫龋膶?duì)象普通對(duì)象和函數(shù)對(duì)象都會(huì)有屬性,指向創(chuàng)建它的構(gòu)造函數(shù)的原型對(duì)象,比如上面的例子這就形成了原型鏈,會(huì)一直查找原型對(duì)象的屬性,直到為。,保證原型鏈能夠正常結(jié)束。
前言
一般談到j(luò)s中的繼承的時(shí)候,一定會(huì)遇到原型,原型鏈的問(wèn)題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學(xué)是不是都一頭霧水,傻傻分不清楚,因?yàn)楣ぷ髦杏玫降牡胤绞巧僦稚伲偌由蟚s6又出了extends語(yǔ)法糖,更加不用理會(huì)之,但是對(duì)于理解繼承,原型和原型鏈?zhǔn)呛苤匾模斫夂瘮?shù)和對(duì)象,理解prototype和__proto__,construct之間的關(guān)系尤為重要,不過(guò)本文對(duì)繼承不予以深究,另起一篇文章寫之,今天我們只討論js中的原型和原型鏈。
首先,容在下提出一個(gè)問(wèn)題。
到底prototype和__proto__是不是指同一個(gè)東西呢?
答案自然非也。
還有一個(gè)問(wèn)題,就是ie8,9下是沒(méi)有__proto__的概念的,如何解決這個(gè)問(wèn)題?
這個(gè)問(wèn)題在這篇文章結(jié)束之前會(huì)說(shuō)明。
現(xiàn)在我們先來(lái)分析js中的對(duì)象。
js中對(duì)象是很重要的,所謂萬(wàn)物皆對(duì)象,但是js中對(duì)象分為兩種,普通對(duì)象和函數(shù)對(duì)象
先來(lái)看幾個(gè)例子
function f1(){}; var f2 = function(){}; var f3 = new Function("str","console.log(str)"); var o3 = new f1(); var o1 = {}; var o2 = new Object(); console.log(typeof Object); //function console.log(typeof Function); //function console.log(typeof o1); //object console.log(typeof o2); //object console.log(typeof o3); //object console.log(typeof f1); //function console.log(typeof f2); //function console.log(typeof f3); //function
在上面的例子中,o1 o2 o3 為普通對(duì)象,f1 f2 f3 為函數(shù)對(duì)象。
那么怎么區(qū)分普通對(duì)象和函數(shù)對(duì)象呢?
其實(shí)很簡(jiǎn)單,凡是通過(guò)new Function()創(chuàng)建的對(duì)象都是函數(shù)對(duì)象,其他的都是普通對(duì)象。f1,f2,歸根結(jié)底都是通過(guò) new Function()的方式進(jìn)行創(chuàng)建的。Function Object 也都是通過(guò) New Function()創(chuàng)建的。
接下來(lái)先說(shuō)一下原型對(duì)象
在js中,每當(dāng)定義一個(gè)對(duì)象的時(shí)候,對(duì)象中都會(huì)包含一些預(yù)定義的屬性。其中函數(shù)對(duì)象的一個(gè)屬性就是原型對(duì)象prototype。
普通對(duì)象沒(méi)有prototype,只有__proto__屬性,看下面的例子
function f1(){}; console.log(f1.prototype) //{constructor:? f1(),__proto__:Object} console.log(typeof f1.prototype) //Object console.log(typeof Function.prototype) // Function,這個(gè)特殊,因?yàn)镕unction是通過(guò)new Function創(chuàng)建的 console.log(typeof Object.prototype) // Object console.log(typeof Function.prototype.prototype) //undefined
從console.log(f1.prototype) //{constructor:? f1(),__proto__:Object}可以看出f1.prototype就是f1的一個(gè)實(shí)例對(duì)象,就是在創(chuàng)建f1的時(shí)候,創(chuàng)建了一個(gè)它的實(shí)例對(duì)象,并把它賦給了prototype原型對(duì)象。代碼如下
const temp = new f1(); f1.prototype = temp;
那么看到這兒,大家肯定會(huì)說(shuō),為什么要有原型對(duì)象?這個(gè)原型對(duì)象有什么用?
剛開始我就提到了,繼承里會(huì)用到。看下下面的代碼:
function Cat(name){ this.name = name; } Cat.prototype.getName = function(){ alert(this.name); } const qqq = new Cat("qqq"); qqq.getName();//qqq
從上面的代碼中可以看出,通過(guò)給Cat的原型對(duì)象添加屬性方法,那么Cat的實(shí)例都會(huì)擁有這個(gè)方法并可以調(diào)用之。有同學(xué)可能會(huì)有疑問(wèn),為什么在原型對(duì)象上添加了屬性方法,它的實(shí)例就也可以擁有這個(gè)方法呢?這就牽扯到接下來(lái)說(shuō)到的原型鏈了。
原型鏈首先,js的對(duì)象(普通對(duì)象和函數(shù)對(duì)象)都會(huì)有__proto__屬性,指向創(chuàng)建它的構(gòu)造函數(shù)的原型對(duì)象,比如上面的例子
qqq.__proto__ === Cat.prototype;//true Cat.prototype.__proto__ === Object.prototype;//true Object.prototype.__proto__//null
這就形成了原型鏈,會(huì)一直查找原型對(duì)象的__proto__屬性,直到為null。
有幾個(gè)比較特殊的例子,來(lái)看一下
1.Object.__proto__ === Function.prototype // true
Object是函數(shù)對(duì)象,是通過(guò)new Function()創(chuàng)建,所以O(shè)bject.__proto__指向Function.prototype。
2.Function.__proto__ === Function.prototype // true
Function 也是對(duì)象函數(shù),也是通過(guò)new Function()創(chuàng)建,所以Function.__proto__指向Function.prototype。
3.Function.prototype.__proto__ === Object.prototype //true
Function.prototype是個(gè)函數(shù)對(duì)象,理論上他的__proto__應(yīng)該指向 Function.prototype,就是他自己,自己指向自己,沒(méi)有意義。
JS一直強(qiáng)調(diào)萬(wàn)物皆對(duì)象,函數(shù)對(duì)象也是對(duì)象,給他認(rèn)個(gè)祖宗,指向Object.prototype。Object.prototype.__proto__ === null,保證原型鏈能夠正常結(jié)束。
constructor是這么定義的。
在 Javascript 語(yǔ)言中,constructor 屬性是專門為 function 而設(shè)計(jì)的,它存在于每一個(gè) function 的prototype 屬性中。這個(gè) constructor 保存了指向 function 的一個(gè)引用。
Cat.prototype.constructor === Cat //true Function.prototype.constructor === Function //true Object.prototype.constructor === Object //true
這里也有要注意的
1.注意Object.constructor===Function;//true 本身Object就是Function函數(shù)構(gòu)造出來(lái)的
2.如何查找一個(gè)對(duì)象的constructor,就是在該對(duì)象的原型鏈上尋找碰到的第一個(gè)constructor屬性所指向的對(duì)象
1.原型和原型鏈?zhǔn)菍?shí)現(xiàn)繼承的一種方式
2.原型鏈真正的繼承是靠__proto__,而不是prototype,且看以下這個(gè)例子
var animal = function(name){ this.name = name; } var cat = function(){}; animal.say = "lalala"; cat.prototype = animal; var ca = new cat(); console.log(cat.say);//undefined console.log(ca.say);//lalala
從輸出結(jié)果可以看出,雖然cat的prototype指向了animal,但是讀取say屬性的時(shí)候并不會(huì)根據(jù)prototype找,ca本身雖然也沒(méi)有say屬性,但是看下面這段代碼
ca.__proto__ = cat.prototype cat.prototype = animal
所以ca.say輸出lalala
3.之前遺留的問(wèn)題,關(guān)于兼容ie的__proto__
ie9有Object.getPrototypeof()方法
function a(){console.log("aaa")}; const b = new a(); Object.getPrototypeof(b) === b.__proto__//true
ie8不支持Object.getPrototypeof方法,可以結(jié)合constructor和prototype
function a(){console.log("aaa")}; const b = new a(); b.constructor.prototype === b.__proto__//true
最后再思考下new()過(guò)程都做了些什么?(比如new A())
創(chuàng)建新對(duì)象var obj = {};
將新對(duì)象的construct屬性指向構(gòu)造函數(shù),__proto__屬性指向構(gòu)造函數(shù)的prototype
執(zhí)行構(gòu)造函數(shù),A.call(obj),將this指向obj
返回新對(duì)象(注意:如果構(gòu)造函數(shù)返回this,基本類型或者不返回,就是返回新對(duì)象,如果返回引用類型,就是返回引用類型)
好了,今天就先寫這么多,明天結(jié)合今天的原型和原型鏈總結(jié)下繼承以及每個(gè)繼承的優(yōu)缺點(diǎn)~~~
參考資料
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108282.html
摘要:只是構(gòu)造函數(shù)上的一個(gè)屬性,它是一個(gè)指針,指向原型對(duì)象,并不表示就是原型對(duì)象。在上一個(gè)例子中,就是一個(gè)對(duì)象,這個(gè)對(duì)象可以說(shuō)是原生構(gòu)造函數(shù)的實(shí)例,所以也是一個(gè)對(duì)象,所以它也有屬性,不過(guò)它的指向也就是原型鏈的頂端,再往上就沒(méi)有了。 上一篇講了①原型對(duì)象是什么;②__proto__、prototype、constructor的關(guān)系;③原型對(duì)象的作用;④原型對(duì)象帶來(lái)的一些需要注意的問(wèn)題; 沒(méi)理解...
摘要:雖然今年沒(méi)有換工作的打算但為了跟上時(shí)代的腳步還是忍不住整理了一份最新前端知識(shí)點(diǎn)知識(shí)點(diǎn)匯總新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式和的區(qū)別使用的好處標(biāo)簽廢棄的標(biāo)簽,和一些定位寫法放置位置和原因什么是漸進(jìn)式渲染模板語(yǔ)言原理盒模型,新特性,偽 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總1.HTMLHTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪...
摘要:雖然今年沒(méi)有換工作的打算但為了跟上時(shí)代的腳步還是忍不住整理了一份最新前端知識(shí)點(diǎn)知識(shí)點(diǎn)匯總新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式和的區(qū)別使用的好處標(biāo)簽廢棄的標(biāo)簽,和一些定位寫法放置位置和原因什么是漸進(jìn)式渲染模板語(yǔ)言原理盒模型,新特性,偽 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總1.HTMLHTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪...
摘要:無(wú)獨(dú)有偶,在中國(guó)古代社會(huì),也有姓名巫術(shù)這一說(shuō)。從匿名到偽匿名此時(shí),具有匿名性的區(qū)塊鏈走入了人們的視野,除了去中心化安全性可追溯性等特征外,區(qū)塊鏈被提及最多的就是其匿名性。因此,區(qū)塊鏈的完全匿名或完全實(shí)名是不可能的。 從姓名巫術(shù)到匿名文化 姓名,是一個(gè)人最基礎(chǔ)的社會(huì)符號(hào),是人們相互了解的一個(gè)窗口。然而,在科技落后的古代,人們對(duì)名字被人知曉諱莫如深。因?yàn)樗麄冋J(rèn)為,姓名與靈魂共生。 在印第安...
摘要:要快,但是我們的服務(wù)也必須萬(wàn)無(wú)一失,后續(xù)我會(huì)分享百度移動(dòng)端首頁(yè)的前端架構(gòu)設(shè)計(jì)那么這樣的優(yōu)化,是如何做到的呢,又如何兼顧穩(wěn)定性,架構(gòu)性,與速度呢別急,讓我們把這些優(yōu)化一一道來(lái)。百度移動(dòng)端首頁(yè)的很多就是這樣緩存在客戶端的。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fronte...
閱讀 2671·2021-11-11 16:54
閱讀 1374·2021-09-22 15:23
閱讀 3827·2021-09-07 09:59
閱讀 2268·2021-09-02 15:41
閱讀 3437·2021-08-17 10:13
閱讀 3249·2019-08-30 15:53
閱讀 1375·2019-08-30 13:57
閱讀 1362·2019-08-29 15:16