摘要:在創建對象不論是普通對象還是函數對象的時候,都有一個叫做的內置屬性,用于指向創建它的構造函數的原型對象,也就是。因為一個普通對象的構造函數所以原型鏈原型鏈的形成是真正是靠而非。參考文章最詳盡的原型與原型鏈終極詳解,沒有可能是。
【前端芝士樹】Javascript的原型、原型鏈以及繼承機制
前端的面試中經常會遇到這個問題,自己也是一直似懂非懂,趁這個機會整理一下0. 為什么會出現原型和原型鏈的概念
1994年,網景公司(Netscape)發布了Navigator瀏覽器0.9版,但是剛開始的Js沒有繼承機制,更別提像同時期興盛的C++和Java這樣擁有面向對象的概念。在實際的開發過程中,工程師們發現沒有繼承機制很難解決一些問題,必須有一種機制能將所有的對象關聯起來。
Brendan Eich鑒于以上情況,但不想把Js設計得過為復雜,于是引入了new關鍵詞 和 constructor構造函數來簡化對象的設計,引入了prototype函數對象來包含所有實例對象的構造函數的屬性和方法,引入了proto和原型鏈的概念解決繼承的問題。
1. Javscript 函數和函數對象var o1 = {}; var o2 =new Object(); var o3 = new f1(); function f1(){}; var f2 = function(){}; var f3 = new Function("str","console.log(str)");
凡是直接或者間接通過 new Function() 創建的對象都是函數對象,其他的都是普通對象。
在上面的程序中,o1、o2、o3都是普通對象,f1、f2、f3都是函數對象。
2. 構造函數function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name) } } var person1 = new Person("Zaxlct", 28, "Software Engineer"); var person2 = new Person("Mick", 23, "Doctor");
person1 和 person2 都是 構造函數 Person 的實例。3. 原型對象
實例的構造函數屬性(constructor)指向構造函數。
Person.prototype = { name: "Zaxlct", age: 28, job: "Software Engineer", sayName: function() { alert(this.name); } }
每個函數對象都有一個 prototype 屬性,這個屬性就是函數的原型對象。
每個對象都有 proto 屬性,但只有函數對象才有 prototype 屬性
在默認情況下,所有的原型對象都會自動獲得一個 constructor(構造函數)屬性,這個屬性(是一個指針)指向 prototype 屬性所在的函數(Person)
Person.prototype.constructor == Person
而在Person這個對象進行實例化的時候,實際上是創建了一個它的實例對象并賦值給它的 prototype,所以得出以下結論:
原型對象(Person.prototype)是 構造函數(Person)的一個實例。4. _proto_
JS 在創建對象(不論是普通對象還是函數對象)的時候,都有一個叫做__proto__ 的內置屬性,用于指向創建它的構造函數的原型對象,也就是prototype。
Person.prototype.constructor == Person; person1.__proto__ == Person.prototype; person1.constructor == Person;
看下面一段代碼
Person.prototype.__proto__ === Object.prototype;
Person.prototype 是一個普通對象,我們無需關注它有哪些屬性,只要記住它是一個普通對象。
因為一個 普通對象的構造函數 === Object
所以 Person.prototype.__proto__ === Object.prototype
原型鏈的形成是真正是靠__proto__ 而非prototype。
person1.__proto__ === Person.prototype; Person.prototype.__proto__ === Object.prototype; Object.prototype.__proto__ === null; //Object.prototype.__proto__ === null,保證原型鏈能夠正常結束。 Person.__proto__ === Function.prototype; Object.__proto__ === Function.prototype; Function.prototype.__proto__ === Object.prototype;
前面三項已經形成了一個原型鏈,那么后面代碼中Person和Object的__proto__都是Function.prototype呢?
所有函數對象的proto都指向Function.prototype,它是一個空函數(Empty function)
Number.__proto__ === Function.prototype // true Number.constructor == Function //true Boolean.__proto__ === Function.prototype // true Boolean.constructor == Function //true String.__proto__ === Function.prototype // true String.constructor == Function //true Object.__proto__ === Function.prototype // true Object.constructor == Function // true Function.__proto__ === Function.prototype // true Function.constructor == Function //true Array.__proto__ === Function.prototype // true Array.constructor == Function //true RegExp.__proto__ === Function.prototype // true RegExp.constructor == Function //true Error.__proto__ === Function.prototype // true Error.constructor == Function //true Date.__proto__ === Function.prototype // true Date.constructor == Function //true
所有的構造器都來自于 Function.prototype,甚至包括根構造器Object及Function自身。所有構造器都繼承了·Function.prototype·的屬性及方法。如length、call、apply、bind
所以我們再舉一個原型鏈的例子
let num = new Number(); num.__proto__ === Number.prototype; Number.prototype.__proto__ === Function.prototype; Funtion.prototype.__proto__ === Object.prototype; Object.prototype.__proto__ === null;
也可看下圖的實現,更直觀。
ok, 所以明白為什么Number、String、Array這樣的對象實例能繼承到Object的屬性以及原型鏈是怎么一回事了吧。
參考文章
最詳盡的 JS 原型與原型鏈終極詳解,沒有「可能是」。
三張圖搞懂JavaScript的原型對象與原型鏈 - 水乙 - 博客園
Javascript繼承機制的設計思想 - 阮一峰的網絡日志
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98270.html
摘要:沒有找到的話,看上級函數作用域,向上查找到,找到為止。將會在執行上下文棧中保留上級作用域的執行上下文。若在閉包使用完畢之后不手動解除引用,相關執行上下文將會一直保留于執行上下文棧中,占據內存空間,若持續積累,容易造成內存泄漏。 JS有哪些基本數據類型呢? 值類型:undefined, Number, Boolean, String,null 引用類型:Object 值類型存放在棧中 引...
摘要:而像和會增加作用域鏈的長度,所以也會降低性能。但是用獲取一些屬性時,會不由自主地強迫隊列中的所有渲染事件前不完成。在條件增加時,所帶來的性能負擔要高于,因此建議使用。它代價昂貴,且容易失控。 正巧看到在送書,于是乎找了找自己博客上記錄過的一些東西來及其無恥的蹭書了~~~ 小廣告:更多內容可以看我的博客 以下內容均來自《高性能JavaScript》 JavaScript文件加載 ...
摘要:而像和會增加作用域鏈的長度,所以也會降低性能。但是用獲取一些屬性時,會不由自主地強迫隊列中的所有渲染事件前不完成。在條件增加時,所帶來的性能負擔要高于,因此建議使用。它代價昂貴,且容易失控。 正巧看到在送書,于是乎找了找自己博客上記錄過的一些東西來及其無恥的蹭書了~~~ 小廣告:更多內容可以看我的博客 以下內容均來自《高性能JavaScript》 JavaScript文件加載 ...
摘要:借用構造函數類式繼承借用構造函數雖然解決了剛才兩種問題,但沒有原型,則復用無從談起。 寫在前面 【前端指南】前端面試庫已經開源,正在完善之中 [x] css問題 [x] html問題 [x] javascript問題 github地址 https://github.com/nanhupatar... showImg(https://segmentfault.com/img...
1. JS基本的數據類型和引用類型 基本數據類型:number、string、null、undefined、boolean、symbol -- 棧 引用數據類型:object、array、function -- 堆 兩種數據類型存儲位置不同 原始數據類型是直接存儲在棧(stack)中的簡單數據段,占據空間小、大小固定,屬于被頻繁使用數據; 引用數據類型存儲在堆(heap)中的對象,占據空間大、大...
閱讀 2293·2021-11-24 09:39
閱讀 2535·2021-11-22 15:24
閱讀 2976·2021-09-02 09:48
閱讀 3010·2021-07-26 22:01
閱讀 1433·2019-08-30 11:09
閱讀 1673·2019-08-29 18:47
閱讀 601·2019-08-29 15:40
閱讀 2132·2019-08-29 15:22