摘要:實(shí)際上要分三種情況來(lái)看如果在鏈上存在這個(gè)屬性,并且沒(méi)有標(biāo)記為只讀,那么就會(huì)在本對(duì)象上新建一個(gè)新的同名屬性。那么因?yàn)槭且茫酝ㄟ^(guò)改變其原型上的的值,里也會(huì)跟著改變。反之,則新建一個(gè)對(duì)象。而這個(gè)引用鏈?zhǔn)强梢愿鶕?jù)自己的需求去改。
首先呢,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ì)象也就跟著變了。
很簡(jiǎn)單吧,那么如果執(zhí)行如下代碼的話,會(huì)發(fā)生什么呢?
myObj.a = 10;
是不是認(rèn)為,還跟上面那個(gè)一樣的,obj.a也變成10了呢?實(shí)際上不是的,他的運(yùn)行機(jī)制要比咱們想的稍微復(fù)雜一點(diǎn)點(diǎn)。
實(shí)際上要分三種情況來(lái)看:
如果在prototype鏈上存在這個(gè)屬性,并且沒(méi)有標(biāo)記為只讀,那么就會(huì)在本對(duì)象上新建一個(gè)新的同名屬性。
如果在prototype鏈上存在這個(gè)屬性,并且標(biāo)記為只讀,那么將無(wú)法修改已有屬性或在本對(duì)象上新建一個(gè)同名屬性,如果是嚴(yán)格模式的話,還會(huì)報(bào)錯(cuò)。
如果在prototype鏈上只是存在此setter,那么一定會(huì)調(diào)用此setter,并不會(huì)添加屬性到對(duì)象上,更不會(huì)重新定義這個(gè)setter
很枯燥是吧,來(lái)看例子,對(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的一些特性,接下來(lái),咱們就要講關(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的過(guò)程中呢,生成了一個(gè)新對(duì)象,并且把Foo.prototype引用到了新對(duì)象的prototype。那么因?yàn)槭且?,所以通過(guò)b改變其原型上的prototype的值,F(xiàn)oo.prototype里也會(huì)跟著改變。
那么new的過(guò)程,是不是一定引用的是函數(shù)的prototype呢?也不一定,比如說(shuō)下面的例子。
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
甚至說(shuō),F(xiàn)oo.prototype也是可以被改變的,不過(guò)在這時(shí)候,new出來(lái)的對(duì)象,其prototype就是被改過(guò)的那個(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。
所以說(shuō)結(jié)論吧,在new的時(shí)候,實(shí)際上執(zhí)行會(huì)包含這么幾步,
如果有return并且返回的是一個(gè)對(duì)象的話,則直接返回return后的那個(gè)對(duì)象。
反之,則新建一個(gè)對(duì)象。
并且吧函數(shù)的prototype引用到新建對(duì)象的prototype中。
所以說(shuō),原型,可以理解為我本來(lái)對(duì)象有一個(gè)prototype,引用著其他的對(duì)象,當(dāng)我這個(gè)對(duì)象的prototype引用了另一個(gè)對(duì)象的prototype,一般情況會(huì)到Object.prototype為止,這樣就組成了一個(gè)原型鏈,原型鏈也就是互相引用的引用鏈。而這個(gè)引用鏈?zhǔn)强梢愿鶕?jù)自己的需求去改。
好了,簡(jiǎn)短的一小節(jié)就完事了,如果有不明白的,或者有疏漏的地方,或者有什么地方想和我討論的,可以留言給我哦
本文轉(zhuǎn)載自http://www.lht.ren/article/8/
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100935.html
摘要:在最開始的時(shí)候,原型對(duì)象的設(shè)計(jì)主要是為了獲取對(duì)象的構(gòu)造函數(shù)。同理數(shù)組通過(guò)調(diào)用函數(shù)通過(guò)調(diào)用原型鏈中描述了原型鏈的概念,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法。 對(duì)象的創(chuàng)建 在JavaScript中創(chuàng)建一個(gè)對(duì)象有三種方式??梢酝ㄟ^(guò)對(duì)象直接量、關(guān)鍵字new和Object.create()函數(shù)來(lái)創(chuàng)建對(duì)象。 1. 對(duì)象直接量 創(chuàng)建對(duì)象最直接的方式就是在JavaScript代碼中使用對(duì)象直接量。在ES5...
摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方法和的作用都是在某個(gè)特殊對(duì)象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無(wú)區(qū)別適用情境可以在特殊的情況下用來(lái)為對(duì)象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 1499·2023-04-25 19:00
閱讀 4216·2021-11-17 17:00
閱讀 1827·2021-11-11 16:55
閱讀 1581·2021-10-14 09:43
閱讀 3202·2021-09-30 09:58
閱讀 904·2021-09-02 15:11
閱讀 2164·2019-08-30 12:56
閱讀 1445·2019-08-30 11:12