摘要:實際上要分三種情況來看如果在鏈上存在這個屬性,并且沒有標記為只讀,那么就會在本對象上新建一個新的同名屬性。那么因為是引用,所以通過改變其原型上的的值,里也會跟著改變。反之,則新建一個對象。而這個引用鏈是可以根據自己的需求去改。
首先呢,prototype是對象里的一個內置屬性,并且呢,這個屬性是對于其他對象的一個引用。所以呢,思考下面的例子:
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
這里可以看到,實際上Object.create()是新建了一個對象,并且這個對象的prototype是obj的一個引用,所以呢,如果咱們直接修改prototype里面的值,原對象也就跟著變了。
很簡單吧,那么如果執行如下代碼的話,會發生什么呢?
myObj.a = 10;
是不是認為,還跟上面那個一樣的,obj.a也變成10了呢?實際上不是的,他的運行機制要比咱們想的稍微復雜一點點。
實際上要分三種情況來看:
如果在prototype鏈上存在這個屬性,并且沒有標記為只讀,那么就會在本對象上新建一個新的同名屬性。
如果在prototype鏈上存在這個屬性,并且標記為只讀,那么將無法修改已有屬性或在本對象上新建一個同名屬性,如果是嚴格模式的話,還會報錯。
如果在prototype鏈上只是存在此setter,那么一定會調用此setter,并不會添加屬性到對象上,更不會重新定義這個setter
很枯燥是吧,來看例子,對照著上面的情況,好好的理解一下:
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
假如上面的已經理解了,那么可以思考下下面的運行結果:
var obj = { a: 2 } var myObj = Object.create(obj); console.log(++myObj.a); // 3 console.log(obj.a); // 2
這個在咱們實際的編碼中時有發生,看代碼是想把a改成3,但是由于上面第一種情況的影響,實際上是新建了一個同名屬性3,并且賦值給了myObj。
上面我們談論的都是普通對象的prototype的一些特性,接下來,咱們就要講關于new關鍵字相關的一些知識點了,思考下面的例子
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的過程中呢,生成了一個新對象,并且把Foo.prototype引用到了新對象的prototype。那么因為是引用,所以通過b改變其原型上的prototype的值,Foo.prototype里也會跟著改變。
那么new的過程,是不是一定引用的是函數的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
在這個例子中,由于new的時候,返回的是一個對象,所以最后實際上a最終引用的是Foo最后返回的那個小對象,所以其prototype就是Object.prototype,而不是Foo.prototype
甚至說,Foo.prototype也是可以被改變的,不過在這時候,new出來的對象,其prototype就是被改過的那個對象。
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修改了默認的Foo.prototype,所以最后,實際上形成了這么一個引用鏈:a.prototype => foo.prototype => protoObj=>Object.prototype。
所以說結論吧,在new的時候,實際上執行會包含這么幾步,
如果有return并且返回的是一個對象的話,則直接返回return后的那個對象。
反之,則新建一個對象。
并且吧函數的prototype引用到新建對象的prototype中。
所以說,原型,可以理解為我本來對象有一個prototype,引用著其他的對象,當我這個對象的prototype引用了另一個對象的prototype,一般情況會到Object.prototype為止,這樣就組成了一個原型鏈,原型鏈也就是互相引用的引用鏈。而這個引用鏈是可以根據自己的需求去改。
好了,簡短的一小節就完事了,如果有不明白的,或者有疏漏的地方,或者有什么地方想和我討論的,可以留言給我哦
本文轉載自http://www.lht.ren/article/8/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100935.html
摘要:在最開始的時候,原型對象的設計主要是為了獲取對象的構造函數。同理數組通過調用函數通過調用原型鏈中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。 對象的創建 在JavaScript中創建一個對象有三種方式??梢酝ㄟ^對象直接量、關鍵字new和Object.create()函數來創建對象。 1. 對象直接量 創建對象最直接的方式就是在JavaScript代碼中使用對象直接量。在ES5...
摘要:三種使用構造函數創建對象的方法和的作用都是在某個特殊對象的作用域中調用函數。這種方式還支持向構造函數傳遞參數。叫法上把函數叫做構造函數,其他無區別適用情境可以在特殊的情況下用來為對象創建構造函數。 一、工廠模式 工廠模式:使用字面量和object構造函數會有很多重復代碼,在此基礎上改進showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 1442·2023-04-25 19:00
閱讀 4135·2021-11-17 17:00
閱讀 1753·2021-11-11 16:55
閱讀 1511·2021-10-14 09:43
閱讀 3108·2021-09-30 09:58
閱讀 850·2021-09-02 15:11
閱讀 2118·2019-08-30 12:56
閱讀 1399·2019-08-30 11:12