摘要:每個(gè)原型對象都有一個(gè)屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)為了驗(yàn)證這一說話,舉個(gè)例子。
本文共 1475 字,讀完只需 6 分鐘一、概述
在 JavaScript 中,是一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語言,但是 JS 本身是沒有 “類” 的概念,JS 是靠原型和原型鏈實(shí)現(xiàn)對象屬性的繼承。
在理解原型前,需要先知道對象的構(gòu)造函數(shù)是什么,構(gòu)造函數(shù)都有什么特點(diǎn)?
1. 構(gòu)造函數(shù)
// 構(gòu)造函數(shù) Person() function Person(name, gender) { this.name = name; this.gender = gender; } var person = new Person("周杰倫", "男"); // 最后創(chuàng)建出來的對象實(shí)例 person person { name: "周杰倫", gender: "男" }
以上代碼,普通函數(shù) Person(),加上 new 關(guān)鍵字后,就構(gòu)造了一個(gè)對象 person
所以構(gòu)造函數(shù)的定義就是普通函數(shù)加上 new 關(guān)鍵字,并總會返回一個(gè)對象。
2. 函數(shù)對象
同時(shí),JS 中的對象分為一般對象和函數(shù)對象。那什么是一般對象,什么又是函數(shù)對象呢?
JavaScript 的類型分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型目前有 6 種(null, undefined, string, number, boolean, Symbol)。 其余的數(shù)據(jù)類型都統(tǒng)稱為 object 數(shù)據(jù)類型,其中,包括 Array, Date, Function等,所以函數(shù)可以稱為函數(shù)對象。
let foo = function(){ } foo.name = "bar"; foo.age = 24; console.log(foo instanceof Function) //true console.log(foo.age) // 24
以上代碼就說明了函數(shù)其實(shí)是一個(gè)對象,也可以具有屬性。
二、原型鏈JavaScript 中的對象,有一個(gè)特殊的 [[prototype]] 屬性, 其實(shí)就是對于其他對象的引用(委托)。當(dāng)我們在獲取一個(gè)對象的屬性時(shí),如果這個(gè)對象上沒有這個(gè)屬性,那么 JS 會沿著對象的 [[prototype]]鏈 一層一層地去找,最后如果沒找到就返回 undefined;
這條一層一層的查找屬性的方式,就叫做原型鏈。
var o1 = { age: 6 }
那么,為什么一個(gè)對象要引用,或者說要委托另外一個(gè)對象來尋找屬性呢?
本文開篇的第一句話,就指出來的,JavaScript 中,和一般的 OOP 語言不同,它沒有 "類"的概念,也就沒有 "模板" 來創(chuàng)建對象,而是通過字面量或者構(gòu)造函數(shù)的方式直接創(chuàng)建對象。那么也就不存在所謂的類的復(fù)制繼承。
三、原型那什么又是原型呢?
既然我們沒有類,就用其他的方式實(shí)現(xiàn)類的行為吧,看下面這句話↓↓。
1. 每個(gè)函數(shù)都有一個(gè)原型屬性 prototype 對象
function Person() { } Person.prototype.name = "JayChou"; // person1 和 person2 都是空對象 var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // JayChou console.log(person2.name) // JayChou
通過構(gòu)造函數(shù)創(chuàng)造的對象,對象在尋找 name 屬性時(shí),找到了 構(gòu)造函數(shù)的 prototype 對象上。
這個(gè)構(gòu)造函數(shù)的 prototype 對象,就是 原型
用示意圖來表示:
查找對象實(shí)例屬性時(shí),會沿著原型鏈向上找,在現(xiàn)代瀏覽器中,標(biāo)準(zhǔn)讓每個(gè)對象都有一個(gè) __proto__ 屬性,指向原型對象。那么,我們可以知道對象實(shí)例和函數(shù)原型對象之間的關(guān)系。
2. 每個(gè)原型對象都有一個(gè) constructor 屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)
為了驗(yàn)證這一說話,舉個(gè)例子。
function Person() {} Person === Person.prototype.constructor; // true
那么對象實(shí)例是構(gòu)造函數(shù)構(gòu)造而來,那么對象實(shí)例是不是也應(yīng)該有一個(gè) constructor 呢?
function Person() {} const person = new Person(); person.constructor === Person // true
但事實(shí)上,對象實(shí)例本身并沒有 constructor 屬性,對象實(shí)例的 constructor 屬性來自于引用了原型對象的 constructor 屬性
person.constructor === Person.prototype.constructor // true
3. 原型鏈頂層:Object.prototype.__proto__ == null
既然 JS 通過原型鏈查找屬性,那么鏈的頂層是什么呢,答案就是 Object 對象,Object 對象其實(shí)也有 __proto__屬性,比較特殊的是 Object.prototype.__proto__ 指向 null, 也就是空。
Object.prototype.__proto__ === null
我們回過頭來看函數(shù)對象:
所有函數(shù)對象的proto都指向Function.prototype,它是一個(gè)空函數(shù)(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 // 所有的構(gòu)造器都來自于Function.prototype,甚至包括根構(gòu)造器Object及Function自身 Object.__proto__ === Function.prototype // true Object.constructor == Function // true // 所有的構(gòu)造器都來自于Function.prototype,甚至包括根構(gòu)造器Object及Function自身 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
所有的構(gòu)造器都來自于 Function.prototype,甚至包括根構(gòu)造器Object及Function自身。所有構(gòu)造器都繼承了·Function.prototype·的屬性及方法。如length、call、apply、bind
以圖會友,這就是網(wǎng)上經(jīng)??吹降?JS 原型和原型鏈關(guān)系圖:
對于以上看似很復(fù)雜的關(guān)系圖,只需要理解 5 點(diǎn):
每個(gè)函數(shù)都有一個(gè)原型屬性 prototype 對象
普通對象的構(gòu)造函數(shù)是 Object(),所以 Person.prototype.__proto__ === Object.prototype
函數(shù)對象都來自于 Function.prototype
函數(shù)對象也是對象,所有 Function.prototype.__proto__ === Object.prototype
記住,所有函數(shù)的默認(rèn)原型都是 Object() 的實(shí)例,所以,Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ 是 null
總結(jié)以上就是 JavaScript 中原型和原型鏈的知識。由于 JS 沒有"類", 所以采用了原型的方式實(shí)現(xiàn)繼承,正確的說法是引用或者委托,因?yàn)閷ο笾g的關(guān)系不是復(fù)制,而是委托。在查找屬性的時(shí)候,引用(委托)原型對象的屬性,也就是我們常說的原型繼承。
歡迎關(guān)注個(gè)人微信訂閱號,專注分享原創(chuàng)文章
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98441.html
摘要:不理解沒關(guān)系,下面會結(jié)合圖例分析上一篇高級程序設(shè)計(jì)筆記創(chuàng)建對象下一篇高級程序設(shè)計(jì)筆記繼承參考之原型鏈的解讀三張圖搞懂的原型對象與原型鏈繼承與原型鏈 文章直接從原型圖解開始的,如果對一些概念不太清除,可以結(jié)合后面幾節(jié)查看 1. 圖解原型鏈 1.1 鐵三角關(guān)系(重點(diǎn)) function Person() {}; var p = new Person(); showImg(https://s...
摘要:前言作為前端高頻面試題之一,相信很多小伙伴都有遇到過這個(gè)問題。 前言 作為前端高頻面試題之一,相信很多小伙伴都有遇到過這個(gè)問題。那么你是否清楚完整的了解它呢? 國際慣例,讓我們先拋出問題: 什么是原型、原型鏈 它們有什么特點(diǎn) 它們能做什么 怎么確定它們的關(guān)系 或許你已經(jīng)有答案,或許你開始有點(diǎn)疑惑,無論是 get 新技能或是簡單的溫習(xí)一次,讓我們一起去探究一番吧 如果文章中有出現(xiàn)紕...
摘要:每一個(gè)由構(gòu)造函數(shù)創(chuàng)建的對象都會默認(rèn)的連接到該神秘對象上。在構(gòu)造方法中也具有類似的功能,因此也稱其為類實(shí)例與對象實(shí)例一般是指某一個(gè)構(gòu)造函數(shù)創(chuàng)建出來的對象,我們稱為構(gòu)造函數(shù)的實(shí)例實(shí)例就是對象。表示該原型是與什么構(gòu)造函數(shù)聯(lián)系起來的。 本文您將看到以下內(nèi)容: 傳統(tǒng)構(gòu)造函數(shù)的問題 一些相關(guān)概念 認(rèn)識原型 構(gòu)造、原型、實(shí)例三角結(jié)構(gòu)圖 對象的原型鏈 函數(shù)的構(gòu)造函數(shù)Function 一句話說明什么...
摘要:既然構(gòu)造函數(shù)有屬于自己的原型對象,那么我們應(yīng)該能讓另一個(gè)構(gòu)造函數(shù)來繼承他的原型對象咯我們在構(gòu)造函數(shù)內(nèi)部執(zhí)行了函數(shù)并改變了函數(shù)內(nèi)部的指向其實(shí)這個(gè)指向的是實(shí)例化之后的對象。 我們在討(mian)論(shi)JavaScript這門語言時(shí),總是繞不過的一個(gè)話題就是繼承與原型鏈。那么繼承與原型鏈到底是什么呢? 我很喜歡的一個(gè)聊天模式是:我不能說XX是什么,我只能說XX像什么。也就是說我不直接跟...
摘要:綜上所述有原型鏈繼承,構(gòu)造函數(shù)繼承經(jīng)典繼承,組合繼承,寄生繼承,寄生組合繼承五種方法,寄生組合式繼承,集寄生式繼承和組合繼承的優(yōu)點(diǎn)于一身是實(shí)現(xiàn)基于類型繼承的最有效方法。 一、前言 繼承是面向?qū)ο螅∣OP)語言中的一個(gè)最為人津津樂道的概念。許多面對對象(OOP)語言都支持兩種繼承方式::接口繼承 和 實(shí)現(xiàn)繼承 。 接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。由于js中方法沒有簽名...
摘要:探索是如何判斷的表達(dá)式如果函數(shù)的顯式原型對象在對象的隱式原型鏈上,返回,否則返回是通過自己產(chǎn)生的實(shí)例案例案例重要注意的顯示原型和隱式原型是一樣的。面試題測試題測試題報(bào)錯(cuò)對照下圖理解 原型與原型鏈深入理解(圖解) 原型(prototype) 函數(shù)的 prototype 屬性(圖) 每個(gè)函數(shù)都有一個(gè)prototype屬性,它默認(rèn)指向一個(gè)Object空對象(即稱為:原型對象) 原型對象中有...
閱讀 3425·2021-11-25 09:43
閱讀 2310·2021-09-06 15:02
閱讀 3551·2021-08-18 10:21
閱讀 3349·2019-08-30 15:55
閱讀 2356·2019-08-29 17:06
閱讀 3540·2019-08-29 16:59
閱讀 971·2019-08-29 13:47
閱讀 2772·2019-08-26 13:24