摘要:當這步完成,這個對象就與構造函數再無聯系,這個時候即使構造函數再加任何成員,都不再影響已經實例化的對象了。此時,對象具有了和屬性,同時具有了構造函數的原型對象的所有成員,當然,此時該原型對象是沒有成員的。
學到原型的時候感覺頭都大了/(ㄒoㄒ)/~~ 尤其是prototype和__proto__ 傻傻分不清,通過多番查找資料,根據自己的理解,記錄下最近研究對象的一些心得,做一個記錄與總結,以加深自己的印象,同時,希望也能給其他學JavaScript同胞一點啟發。
在JavaScript中,萬物皆對象。咱們寫一個JavaScript對象,大多數時候是用構造函數創建一個對象或者用對象字面量創建一個對象。比如:
//通過構造函數來創建對象 function Person() { //... } var person1 = new Person(); //通過對象字面量創建對象 var person2 = { name: "jessica", age: 27, job: "teacher" }
當然還有其他方式創建對象,這里就不列舉出來了。那么問題來了,通過不同的方式創建的對象有什么區別呢?
我們知道,每個JS對象一定對應一個原型對象,并從原型對象繼承屬性和方法。那么對象是怎么和這個原型對象對應的呢?帶著問題慢慢看下面的內容吧
其實說__proto__并不準確,確切的說是對象的[[prototype]]屬性,只不過在主流的瀏覽器中,都用__proto__來代表[[prototype]]屬性,因為[[prototype]]只是一個標準,而針對這個標準,不同的瀏覽器有不同的實現方式。在ES5中用Object.getPrototypeOf函數獲得一個對象的[[prototype]]。ES6中,使用Object.setPrototypeOf可以直接修改一個對象的[[prototype]]。為了方便,我下面的文章用__proto__來代表對象的[[prototype]]。
而prototype屬性是只有函數才特有的屬性,當你創建一個函數時,js會自動為這個函數加上prototype屬性,值是一個空對象。所以,函數在js中是非常特殊的,是所謂的一等公民。
那么__proto__和prototype是怎么聯系起來的呢?讓我們來看下下面的代碼:
function Person(name, age) { this.name = name; this.age = age; } var person1 = new Person("jessica", 27);
當我們new Person()的時候到底發生了什么?
new一個構造函數,相當于實例化一個對象,這期間其實進行了這三個步驟:
創建對象,設為o,即:?var o = {};
上文提到了,每個對象都有__proto__屬性,該屬性指向一個對象,這里,將o對象的__Proto__指向構造函數Person的原型對象(Person.prototype);
將o作為this去調用構造函數Person,從而設置o的屬性和方法并初始化。
當這3步完成,這個o對象就與構造函數Person再無聯系,這個時候即使構造函數Person再加任何成員,都不再影響已經實例化的o對象了。
此時,o對象具有了name和age屬性,同時具有了構造函數Person的原型對象的所有成員,當然,此時該原型對象是沒有成員的。
現在大家都明白了吧,簡單的總結下就是:
js在創建對象的時候,都有一個叫做__proto__的內置屬性,用于指向創建它的函數對象的原型對象prototype
那么一個對象的__proto__屬性究竟怎么決定呢?答案顯而易見了:是由構造該對象的方法決定的。
下面講解三種常見的創建對象方法。
對象字面量比如:
var Person = { name: "jessica", age: 27 }
這種形式就是對象字面量,通過對象字面量構造出的對象,其__proto__指向Object.prototype。
所以,其實Object是一個函數也不難理解了。Object、Function都是是js自帶的函數對象。
可以跑下面的代碼看看:
console.log(typeof Object); console.log(typeof Function);構造函數
就如我前面講的,形如:
function Person(){} var person1 = new Person();
這種形式創建對象的方式就是通過構造函數創建對象,這里的構造函數是Person函數。上面也講過了,通過構造函數創建的對象,其__proto指向的是構造函數的prototype屬性指向的對象。
Object.createvar person1 = { name: "jessica", age: 27 } var person2 = Object.create(person1);
這種情況下,person2的__proto__指向person1。在沒有Object.create函數的時候,人們大多是這樣做的:
Object.create = function(p) { function f(){}; f.prototype = p; return new f(); }
一看大家就會明白了。
總結其實仔細思考下上面提到的三種創建對象的方法,追究其本質,不難發現,最根本的還是利用構造函數再通過new來創建對象。所謂的對象字面量也只不過是語法糖而已,本質上是var o = new Object(); o.xx = xx;o.yy=yy;。 所以,函數真不愧是js中的一等公民呀~
原型鏈既然已經提到了原型,就不得不提一下原型鏈了,畢竟這是實現繼承最關鍵所在,也是js對象精妙所在。
還記得上文提到的一個總結嗎?不記得?沒關系,我貼出來讓大家溫故而知新,哈哈~
js在創建對象的時候,都有一個叫做__proto__的內置屬性,用于指向創建它的函數對象的原型對象prototype
而原型鏈的基本思想就是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。
讓我們再簡單回顧下構造函數、原型和實例的關系:
每個構造函數都有一個原型對象,原型對象包含一個指向構造函數的指針(constructor),而實例則包含一個指向原型對象的內部指針(__proto__)。
我們拿一個例子來講解:
function Person(name, age) { this.name = name; this.age = age; } var person1 = new Person("jessica", 27);
一圖勝前言,我們用畫圖的形式來講解下上面的例子:
從上圖可以看到,其實原型鏈的頂端是Object.prototype.__proto__,也即為null。
總結函數是js中的一等公民,js在創建對象的時候,都有一個叫做__proto__的內置屬性,用于指向創建它的函數對象的原型對象prototype。只有函數有prototype, 當你創建一個函數時,js會自動為這個函數加上prototype屬性,值是一個空對象。
祝大家早日富可敵國,bye~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97677.html
摘要:當這步完成,這個對象就與構造函數再無聯系,這個時候即使構造函數再加任何成員,都不再影響已經實例化的對象了。此時,對象具有了和屬性,同時具有了構造函數的原型對象的所有成員,當然,此時該原型對象是沒有成員的。 前言 本篇文章用來記錄下最近研究對象的一些心得,做一個記錄與總結,以加深自己的印象,同時,希望也能給正在學習中的你一點啟發。本文適合有一定JavaScript基礎的童鞋閱讀。原文戳這...
摘要:原文鏈接關于的原型和原型鏈,看我就夠了一參考鏈接闖關記之原型及原型鏈之原型與原型鏈一篇文章帶你理解原型和原型鏈徹底理解原型鏈一的默認指向圖解和的三角關系原型和原型鏈三張圖搞懂的原型對象與原型鏈 溫故 創建對象的三種方式 通過對象直接量 通過new創建對象 通過Object.create() js中對象分為兩種 函數對象 普通對象 仔細觀察如下代碼 function Foo(na...
摘要:我們用一張圖表示構造函數和實例原型之間的關系好了構造函數和實例原型之間的關系我們已經梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向對象系統的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向對象系統,并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
摘要:我們用一張圖表示構造函數和實例原型之間的關系好了構造函數和實例原型之間的關系我們已經梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向對象系統的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向對象系統,并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
摘要:搞清了構造函數和原型的區別后,就可以繼續了。指向構造函數的原型對象,存在于實例與構造函數的原型對象之間。要注意的是當我們使用下面這種將整個重寫的情況時,會切斷構造函數和原型之間的聯系,也就是說不再指向了,而是指向。 前言 先說一說為什么要搞清楚JavaScript的原型,因為這就是JS的根。JavaScript雖然不是一門傳統的面向對象語言,但它有自己的類和繼承機制,最重要的就是它采用...
閱讀 2405·2021-11-18 10:02
閱讀 1922·2021-10-13 09:40
閱讀 2999·2021-09-07 10:07
閱讀 2105·2021-09-04 16:48
閱讀 1005·2019-08-30 13:18
閱讀 2451·2019-08-29 14:03
閱讀 2921·2019-08-29 12:54
閱讀 3155·2019-08-26 11:41