Javascript基础之-原型(prototype)
首先呢,prototype是對(duì)象里的一個(gè)內(nèi)置屬性,并且呢,這個(gè)屬性是對(duì)于其他對(duì)象的一個(gè)引用。所以呢,思考下面的例子:
var obj = {a: 2 } var myObj = Object.create(obj); console.log(myObj.a); // 2 console.log(myObj === obj); // false console.log(Object.getPrototypeOf(myObj) === obj); // true Object.getPrototypeOf(myObj).a = 4 console.log(obj.a); // 4這里可以看到,實(shí)際上Object.create()是新建了一個(gè)對(duì)象,并且這個(gè)對(duì)象的prototype是obj的一個(gè)引用,所以呢,如果咱們直接修改prototype里面的值,原對(duì)象也就跟著變了。
很簡單吧,那么如果執(zhí)行如下代碼的話,會(huì)發(fā)生什么呢?
myObj.a = 10;是不是認(rèn)為,還跟上面那個(gè)一樣的,obj.a也變成10了呢?實(shí)際上不是的,他的運(yùn)行機(jī)制要比咱們想的稍微復(fù)雜一點(diǎn)點(diǎn)。
實(shí)際上要分三種情況來看:
如果在prototype鏈上存在這個(gè)屬性,并且沒有標(biāo)記為只讀,那么就會(huì)在本對(duì)象上新建一個(gè)新的同名屬性。
如果在prototype鏈上存在這個(gè)屬性,并且標(biāo)記為只讀,那么將無法修改已有屬性或在本對(duì)象上新建一個(gè)同名屬性,如果是嚴(yán)格模式的話,還會(huì)報(bào)錯(cuò)。
如果在prototype鏈上只是存在此setter,那么一定會(huì)調(diào)用此setter,并不會(huì)添加屬性到對(duì)象上,更不會(huì)重新定義這個(gè)setter
很枯燥是吧,來看例子,對(duì)照著上面的情況,好好的理解一下:
var obj = {a: 2,set c(num) {console.log('exec it');} } var myObj = Object.create(obj); myObj.a = 10; console.log(obj.a); // 2 console.log(myObj.a); // 10 Object.defineProperty(obj, 'b', {value: 3,writable: false }) myObj.b = 10; console.log(myObj.b); // 3 myObj.c = 20; // "exec it" console.log(myObj.c); // undefined假如上面的已經(jīng)理解了,那么可以思考下下面的運(yùn)行結(jié)果:
var obj = {a: 2 } var myObj = Object.create(obj); console.log(++myObj.a); // 3 console.log(obj.a); // 2這個(gè)在咱們實(shí)際的編碼中時(shí)有發(fā)生,看代碼是想把a(bǔ)改成3,但是由于上面第一種情況的影響,實(shí)際上是新建了一個(gè)同名屬性3,并且賦值給了myObj。
上面我們談?wù)摰亩际瞧胀▽?duì)象的prototype的一些特性,接下來,咱們就要講關(guān)于new關(guān)鍵字相關(guān)的一些知識(shí)點(diǎn)了,思考下面的例子
function Foo() {} var a = new Foo(); console.log(Object.getPrototypeOf(a) === Foo.prototype); // true var b = new Foo(); Object.getPrototypeOf(b).saySomething = function () {console.log('say something'); } a.saySomething(); // "say something"很明顯,在new的過程中呢,生成了一個(gè)新對(duì)象,并且把Foo.prototype引用到了新對(duì)象的prototype。那么因?yàn)槭且?#xff0c;所以通過b改變其原型上的prototype的值,Foo.prototype里也會(huì)跟著改變。
那么new的過程,是不是一定引用的是函數(shù)的prototype呢?也不一定,比如說下面的例子。
function Foo() {return {a: 3} } var a = new Foo(); console.log(Object.getPrototypeOf(a) === Foo.prototype); // false console.log(Object.getPrototypeOf(a) === Object.prototype); // true console.log(a.a); // 3在這個(gè)例子中,由于new的時(shí)候,返回的是一個(gè)對(duì)象,所以最后實(shí)際上a最終引用的是Foo最后返回的那個(gè)小對(duì)象,所以其prototype就是Object.prototype,而不是Foo.prototype
甚至說,Foo.prototype也是可以被改變的,不過在這時(shí)候,new出來的對(duì)象,其prototype就是被改過的那個(gè)對(duì)象。
var protoObj = {b: 10 } function Foo() {} Foo.prototype = protoObj; var a = new Foo(); console.log(Object.getPrototypeOf(a) === Foo.prototype); // true console.log(Object.getPrototypeOf(a) === protoObj); // true console.log(a.b); // 10你看,如果prototypeObj修改了默認(rèn)的Foo.prototype,所以最后,實(shí)際上形成了這么一個(gè)引用鏈:a.prototype => foo.prototype => protoObj=>Object.prototype。
所以說結(jié)論吧,在new的時(shí)候,實(shí)際上執(zhí)行會(huì)包含這么幾步,
如果有return并且返回的是一個(gè)對(duì)象的話,則直接返回return后的那個(gè)對(duì)象。
反之,則新建一個(gè)對(duì)象。
并且吧函數(shù)的prototype引用到新建對(duì)象的prototype中。
所以說,原型,可以理解為我本來對(duì)象有一個(gè)prototype,引用著其他的對(duì)象,當(dāng)我這個(gè)對(duì)象的prototype引用了另一個(gè)對(duì)象的prototype,一般情況會(huì)到Object.prototype為止,這樣就組成了一個(gè)原型鏈,原型鏈也就是互相引用的引用鏈。而這個(gè)引用鏈?zhǔn)强梢愿鶕?jù)自己的需求去改。
好了,簡短的一小節(jié)就完事了,如果有不明白的,或者有疏漏的地方,或者有什么地方想和我討論的,可以留言給我哦。
本文轉(zhuǎn)載自http://www.lht.ren/article/8/
總結(jié)
以上是生活随笔為你收集整理的Javascript基础之-原型(prototype)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jade的写法
- 下一篇: python测试工具开发面试宝典3web