? ? ? ? 大家好,我是IT修真院北京總院第29期的學(xué)員禚洪宇,一枚正直、純潔、善良的前端程序員今天給大家分享一下,修真院官網(wǎng)JS任務(wù)5深度思考中的知識(shí)點(diǎn)——原型鏈?zhǔn)鞘裁矗坑惺裁垂δ埽咳粝朐L問一個(gè)對(duì)象的原型,應(yīng)該使用什么方法?
1 背景介紹
1.1什么是原型
學(xué)習(xí)原型鏈之前我們首先要明白什么是原型;那么什么是原型呢?我們來簡(jiǎn)單學(xué)習(xí)一下:
只要我們像這樣簡(jiǎn)單的定義一個(gè)函數(shù)foo(),就可以訪問像訪問其他對(duì)象一樣訪問該函數(shù)的屬性:
>>>function foo(a,b){return a*b;}
>>>foo.length
2
>>>foo.constructor
Function()
其實(shí)我們?cè)趧?chuàng)建一個(gè)函數(shù)的時(shí)候,這個(gè)函數(shù)就包括了prototype屬性,它的初始值是一個(gè)空對(duì)象(object),
>>>typeof foo.prototype
"object"
所以我們可以自己在這個(gè)空對(duì)象中添加屬性,像這樣:
>>>foo.prototype = {}
1.2 原型有什么作用
? ? ? ? 簡(jiǎn)述一下prototype屬性的出現(xiàn):
? ? ? ? 第一版瀏覽器無用戶交互—》需要腳本語言—》借鑒C++和Java語言,又想節(jié)省服務(wù)器資源和時(shí)間—》prototype。
? ? ? ? ?由于所有的實(shí)例對(duì)象共享同一個(gè)prototype對(duì)象,那么從外界看起來,prototype對(duì)象就好像是實(shí)例對(duì)象的原型,而實(shí)例對(duì)象則好像"繼承"了prototype對(duì)象一樣。
? ? ? ? ? 這個(gè)屬性包含一個(gè)對(duì)象(以下簡(jiǎn)稱"prototype對(duì)象"),所有實(shí)例對(duì)象需要共享的屬性和方法,都放在這個(gè)對(duì)象里面;那些不需要共享的屬性和方法,就放在構(gòu)造函數(shù)里面。
? ? ? ??而實(shí)例對(duì)象一旦創(chuàng)建,將自動(dòng)引用prototype對(duì)象的屬性和方法。也就是說,實(shí)例對(duì)象的屬性和方法,分成兩種,一種是本地的,另一種是引用的。
2 知識(shí)剖析
2.1 原型鏈?zhǔn)鞘裁?/h3>
? ? ? ? 我們上面說到,每個(gè)構(gòu)造函數(shù)在創(chuàng)建時(shí)都包含一個(gè)屬性prototype,其初始值是一個(gè)空對(duì)象;
原型對(duì)象結(jié)構(gòu):
Function.prototype={?
?constructor :Function,
__proto__:parentprototype,
someprototypeproperties: ...?
?};
? ? ? ?函數(shù)的原型對(duì)象constructor默認(rèn)指向函數(shù)本身,原型對(duì)象除了有原型屬性外,為了實(shí)現(xiàn)繼承,還有一個(gè)原型鏈指針__proto__,該指針指向上一層的原型對(duì)象,而上一層的原型對(duì)象的結(jié)構(gòu)依然類似,這樣利用__proto__一直指向Object的原型對(duì)象上,而Object的原型對(duì)象用Object.prototype.__proto__ = null表示原型鏈的最頂端,如此變形成了javascript的原型鏈繼承,同時(shí)也解釋了為什么所有的javascript對(duì)象都具有Object的基本方法。
2.2 若想訪問一個(gè)對(duì)象的原型,應(yīng)該使用什么方法?
獲取實(shí)例對(duì)象obj的原型對(duì)象,有三種方法
1. obj.__proto__
2. obj.constructor.prototype
3. Object.getPrototypeOf(obj)
上面三種方法之中,前兩種都不是很可靠。最新的ES6標(biāo)準(zhǔn)規(guī)定,__proto__屬性只有瀏覽器才需要部署,其他環(huán)境可以不部署。而obj.constructor.prototype在手動(dòng)改變?cè)蛯?duì)象時(shí),可能會(huì)失效。
3 常見問題
Array.isArray(Array.prototype)輸出什么?
4 解決方案
Array.prototype是Array構(gòu)造函數(shù)實(shí)例的原型,構(gòu)造函數(shù)實(shí)例化后仍為數(shù)組,所以輸出true。
5 擴(kuò)展思考
Q1:? prototype與_proto_是什么關(guān)系
__proto__(隱式原型)、prototype(顯式原型)
A1:?? 顯式原型 explicit prototype property:每一個(gè)函數(shù)在創(chuàng)建之后都會(huì)擁有一個(gè)名為prototype的屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。
隱式原型 implicit prototype link:JavaScript中任意對(duì)象都有一個(gè)內(nèi)置屬性[[prototype]],在ES5之前沒有標(biāo)準(zhǔn)的方法訪問這個(gè)內(nèi)置屬性,但是大多數(shù)瀏覽器都支持通過__proto__來訪問。ES5中有了對(duì)于這個(gè)內(nèi)置屬性標(biāo)準(zhǔn)的Get方法Object.getPrototypeOf().
二者的關(guān)系:
隱式原型指向創(chuàng)建這個(gè)對(duì)象的函數(shù)(constructor)的prototype
Q2:在IE中可以使用_proto_屬性嗎?
A:_proto_將在ES6中進(jìn)行標(biāo)準(zhǔn)化,目前在ES6的草案附錄B中。
Q3:_proto_的兼容性怎么樣?
A:_proto_目前是瀏覽器的內(nèi)置屬性,不同的瀏覽器有不同的情況。
6?參考文獻(xiàn)
參考一:阮一峰:Javascript繼承機(jī)制的設(shè)計(jì)思想
參考二:一個(gè)例子讓你徹底明白原型對(duì)象和原型鏈
參考四:《JavaScript面向?qū)ο缶幊讨改稀?/p>