摘要:原型鏈首先,的對象普通對象和函數對象都會有屬性,指向創建它的構造函數的原型對象,比如上面的例子這就形成了原型鏈,會一直查找原型對象的屬性,直到為。,保證原型鏈能夠正常結束。
前言
一般談到js中的繼承的時候,一定會遇到原型,原型鏈的問題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學是不是都一頭霧水,傻傻分不清楚,因為工作中用到的地方是少之又少,再加上es6又出了extends語法糖,更加不用理會之,但是對于理解繼承,原型和原型鏈是很重要的,理解函數和對象,理解prototype和__proto__,construct之間的關系尤為重要,不過本文對繼承不予以深究,另起一篇文章寫之,今天我們只討論js中的原型和原型鏈。
首先,容在下提出一個問題。
到底prototype和__proto__是不是指同一個東西呢?
答案自然非也。
還有一個問題,就是ie8,9下是沒有__proto__的概念的,如何解決這個問題?
這個問題在這篇文章結束之前會說明。
現在我們先來分析js中的對象。
js中對象是很重要的,所謂萬物皆對象,但是js中對象分為兩種,普通對象和函數對象
先來看幾個例子
function f1(){}; var f2 = function(){}; var f3 = new Function("str","console.log(str)"); var o3 = new f1(); var o1 = {}; var o2 = new Object(); console.log(typeof Object); //function console.log(typeof Function); //function console.log(typeof o1); //object console.log(typeof o2); //object console.log(typeof o3); //object console.log(typeof f1); //function console.log(typeof f2); //function console.log(typeof f3); //function
在上面的例子中,o1 o2 o3 為普通對象,f1 f2 f3 為函數對象。
那么怎么區分普通對象和函數對象呢?
其實很簡單,凡是通過new Function()創建的對象都是函數對象,其他的都是普通對象。f1,f2,歸根結底都是通過 new Function()的方式進行創建的。Function Object 也都是通過 New Function()創建的。
接下來先說一下原型對象
在js中,每當定義一個對象的時候,對象中都會包含一些預定義的屬性。其中函數對象的一個屬性就是原型對象prototype。
普通對象沒有prototype,只有__proto__屬性,看下面的例子
function f1(){}; console.log(f1.prototype) //{constructor:? f1(),__proto__:Object} console.log(typeof f1.prototype) //Object console.log(typeof Function.prototype) // Function,這個特殊,因為Function是通過new Function創建的 console.log(typeof Object.prototype) // Object console.log(typeof Function.prototype.prototype) //undefined
從console.log(f1.prototype) //{constructor:? f1(),__proto__:Object}可以看出f1.prototype就是f1的一個實例對象,就是在創建f1的時候,創建了一個它的實例對象,并把它賦給了prototype原型對象。代碼如下
const temp = new f1(); f1.prototype = temp;
那么看到這兒,大家肯定會說,為什么要有原型對象?這個原型對象有什么用?
剛開始我就提到了,繼承里會用到。看下下面的代碼:
function Cat(name){ this.name = name; } Cat.prototype.getName = function(){ alert(this.name); } const qqq = new Cat("qqq"); qqq.getName();//qqq
從上面的代碼中可以看出,通過給Cat的原型對象添加屬性方法,那么Cat的實例都會擁有這個方法并可以調用之。有同學可能會有疑問,為什么在原型對象上添加了屬性方法,它的實例就也可以擁有這個方法呢?這就牽扯到接下來說到的原型鏈了。
原型鏈首先,js的對象(普通對象和函數對象)都會有__proto__屬性,指向創建它的構造函數的原型對象,比如上面的例子
qqq.__proto__ === Cat.prototype;//true Cat.prototype.__proto__ === Object.prototype;//true Object.prototype.__proto__//null
這就形成了原型鏈,會一直查找原型對象的__proto__屬性,直到為null。
有幾個比較特殊的例子,來看一下
1.Object.__proto__ === Function.prototype // true
Object是函數對象,是通過new Function()創建,所以Object.__proto__指向Function.prototype。
2.Function.__proto__ === Function.prototype // true
Function 也是對象函數,也是通過new Function()創建,所以Function.__proto__指向Function.prototype。
3.Function.prototype.__proto__ === Object.prototype //true
Function.prototype是個函數對象,理論上他的__proto__應該指向 Function.prototype,就是他自己,自己指向自己,沒有意義。
JS一直強調萬物皆對象,函數對象也是對象,給他認個祖宗,指向Object.prototype。Object.prototype.__proto__ === null,保證原型鏈能夠正常結束。
constructor是這么定義的。
在 Javascript 語言中,constructor 屬性是專門為 function 而設計的,它存在于每一個 function 的prototype 屬性中。這個 constructor 保存了指向 function 的一個引用。
Cat.prototype.constructor === Cat //true Function.prototype.constructor === Function //true Object.prototype.constructor === Object //true
這里也有要注意的
1.注意Object.constructor===Function;//true 本身Object就是Function函數構造出來的
2.如何查找一個對象的constructor,就是在該對象的原型鏈上尋找碰到的第一個constructor屬性所指向的對象
1.原型和原型鏈是實現繼承的一種方式
2.原型鏈真正的繼承是靠__proto__,而不是prototype,且看以下這個例子
var animal = function(name){ this.name = name; } var cat = function(){}; animal.say = "lalala"; cat.prototype = animal; var ca = new cat(); console.log(cat.say);//undefined console.log(ca.say);//lalala
從輸出結果可以看出,雖然cat的prototype指向了animal,但是讀取say屬性的時候并不會根據prototype找,ca本身雖然也沒有say屬性,但是看下面這段代碼
ca.__proto__ = cat.prototype cat.prototype = animal
所以ca.say輸出lalala
3.之前遺留的問題,關于兼容ie的__proto__
ie9有Object.getPrototypeof()方法
function a(){console.log("aaa")}; const b = new a(); Object.getPrototypeof(b) === b.__proto__//true
ie8不支持Object.getPrototypeof方法,可以結合constructor和prototype
function a(){console.log("aaa")}; const b = new a(); b.constructor.prototype === b.__proto__//true
最后再思考下new()過程都做了些什么?(比如new A())
創建新對象var obj = {};
將新對象的construct屬性指向構造函數,__proto__屬性指向構造函數的prototype
執行構造函數,A.call(obj),將this指向obj
返回新對象(注意:如果構造函數返回this,基本類型或者不返回,就是返回新對象,如果返回引用類型,就是返回引用類型)
好了,今天就先寫這么多,明天結合今天的原型和原型鏈總結下繼承以及每個繼承的優缺點~~~
參考資料
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108282.html
摘要:只是構造函數上的一個屬性,它是一個指針,指向原型對象,并不表示就是原型對象。在上一個例子中,就是一個對象,這個對象可以說是原生構造函數的實例,所以也是一個對象,所以它也有屬性,不過它的指向也就是原型鏈的頂端,再往上就沒有了。 上一篇講了①原型對象是什么;②__proto__、prototype、constructor的關系;③原型對象的作用;④原型對象帶來的一些需要注意的問題; 沒理解...
摘要:雖然今年沒有換工作的打算但為了跟上時代的腳步還是忍不住整理了一份最新前端知識點知識點匯總新特性,語義化瀏覽器的標準模式和怪異模式和的區別使用的好處標簽廢棄的標簽,和一些定位寫法放置位置和原因什么是漸進式渲染模板語言原理盒模型,新特性,偽 雖然今年沒有換工作的打算 但為了跟上時代的腳步 還是忍不住整理了一份最新前端知識點 知識點匯總1.HTMLHTML5新特性,語義化瀏覽器的標準模式和怪...
摘要:雖然今年沒有換工作的打算但為了跟上時代的腳步還是忍不住整理了一份最新前端知識點知識點匯總新特性,語義化瀏覽器的標準模式和怪異模式和的區別使用的好處標簽廢棄的標簽,和一些定位寫法放置位置和原因什么是漸進式渲染模板語言原理盒模型,新特性,偽 雖然今年沒有換工作的打算 但為了跟上時代的腳步 還是忍不住整理了一份最新前端知識點 知識點匯總1.HTMLHTML5新特性,語義化瀏覽器的標準模式和怪...
摘要:無獨有偶,在中國古代社會,也有姓名巫術這一說。從匿名到偽匿名此時,具有匿名性的區塊鏈走入了人們的視野,除了去中心化安全性可追溯性等特征外,區塊鏈被提及最多的就是其匿名性。因此,區塊鏈的完全匿名或完全實名是不可能的。 從姓名巫術到匿名文化 姓名,是一個人最基礎的社會符號,是人們相互了解的一個窗口。然而,在科技落后的古代,人們對名字被人知曉諱莫如深。因為他們認為,姓名與靈魂共生。 在印第安...
摘要:要快,但是我們的服務也必須萬無一失,后續我會分享百度移動端首頁的前端架構設計那么這樣的優化,是如何做到的呢,又如何兼顧穩定性,架構性,與速度呢別急,讓我們把這些優化一一道來。百度移動端首頁的很多就是這樣緩存在客戶端的。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fronte...
閱讀 2395·2021-11-11 16:54
閱讀 1204·2021-09-22 15:23
閱讀 3644·2021-09-07 09:59
閱讀 1990·2021-09-02 15:41
閱讀 3283·2021-08-17 10:13
閱讀 3037·2019-08-30 15:53
閱讀 1235·2019-08-30 13:57
閱讀 1210·2019-08-29 15:16