亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript 原型中的哲學(xué)思想

sugarmo / 2501人閱讀

摘要:而作為構(gòu)造函數(shù),需要有個(gè)屬性用來(lái)作為以該構(gòu)造函數(shù)創(chuàng)造的實(shí)例的繼承。

歡迎來(lái)我的博客閱讀:「JavaScript 原型中的哲學(xué)思想」

記得當(dāng)年初試前端的時(shí)候,學(xué)習(xí)JavaScript過(guò)程中,原型問(wèn)題一直讓我疑惑許久,那時(shí)候捧著那本著名的紅皮書(shū),看到有關(guān)原型的講解時(shí),總是心存疑慮。

當(dāng)在JavaScript世界中走過(guò)不少旅程之后,再次萌發(fā)起研究這部分知識(shí)的欲望,翻閱了不少書(shū)籍和資料,才搞懂__proto__prototype的概念。

故以作此筆記,日后忘了可以回來(lái)看看。如果你看的過(guò)程中覺(jué)得理解有些困難,把例子在代碼中跑一跑,親手試一試也許能解決不少疑惑。

一切皆為對(duì)象

殊不知,JavaScript的世界中的對(duì)象,追根溯源來(lái)自于一個(gè) null

「一切皆為對(duì)象」,這句著實(shí)是一手好營(yíng)銷,易記,易上口,印象深刻。

萬(wàn)物初生時(shí),一個(gè)null對(duì)象,憑空而生,接著Object、Function學(xué)著null的模樣塑造了自己,并且它們彼此之間喜結(jié)連理,提供了prototypeconstructor,一個(gè)給子孫提供了基因,一個(gè)則制造萬(wàn)千子子孫孫。

在JavaScript中,null也是作為一個(gè)對(duì)象存在,基于它繼承的子子孫孫,當(dāng)屬對(duì)象。乍一看,null像是上帝,而ObjectFunction猶如JavaScript世界中的亞當(dāng)夏娃。

原型指針 __proto__

在JavaScript中,每個(gè)對(duì)象都擁有一個(gè)原型對(duì)象,而指向該原型對(duì)象的內(nèi)部指針則是__proto__,通過(guò)它可以從中繼承原型對(duì)象的屬性,原型是JavaScript中的基因鏈接,有了這個(gè),才能知道這個(gè)對(duì)象的祖祖輩輩。從對(duì)象中的__proto__可以訪問(wèn)到他所繼承的原型對(duì)象。

var a = new Array();
a.__proto__ === Array.prototype // true

上面代碼中,創(chuàng)建了一個(gè)Array的實(shí)例a,該實(shí)例的原型指向了Array.prototype。
Array.prototype本身也是一個(gè)對(duì)象,也有繼承的原型:

a.__proto__.__proto__ === Object.prototype  // true
// 等同于 Array.prototype.__proto__ === Object.prototype

這就說(shuō)了明了,Array本身也是繼承自O(shè)bject的,那么Object的原型指向的是誰(shuí)呢?

a.__proto__.__proto__.__proto__ === null  // true
// 等同于 Object.prototype.__proto__ === null

所以說(shuō),JavaScript中的對(duì)象,追根溯源都是來(lái)自一個(gè)null對(duì)象。佛曰:萬(wàn)物皆空,善哉善哉。

除了使用.__proto__方式訪問(wèn)對(duì)象的原型,還可以通過(guò)Object.getPrototypeOf方法來(lái)獲取對(duì)象的原型,以及通過(guò)Object.setPrototypeOf方法來(lái)重寫對(duì)象的原型。

值得注意的是,按照語(yǔ)言標(biāo)準(zhǔn),__proto__屬性只有瀏覽器才需要部署,其他環(huán)境可以沒(méi)有這個(gè)屬性,而且前后的兩根下劃線,表示它本質(zhì)是一個(gè)內(nèi)部屬性,不應(yīng)該對(duì)使用者暴露。因此,應(yīng)該盡量少用這個(gè)屬性,而是用 Object.getPrototypeofObject.setPrototypeOf,進(jìn)行原型對(duì)象的讀寫操作。這里用__proto__屬性來(lái)描述對(duì)象中的原型,是因?yàn)檫@樣來(lái)得更加形象,且容易理解。

原型對(duì)象 prototype

函數(shù)作為JavaScript中的一等公民,它既是函數(shù)又是對(duì)象,函數(shù)的原型指向的是Function.prototype

var Foo = function() {}
Foo.__proto__ === Function.prototype // true

函數(shù)實(shí)例除了擁有__proto__屬性之外,還擁有prototype屬性。通過(guò)該函數(shù)構(gòu)造的新的實(shí)例對(duì)象,其原型指針__proto__會(huì)指向該函數(shù)的prototype屬性。

var a = new Foo();
a.__proto__ === Foo.prototype; // true

而函數(shù)的prototype屬性,本身是一個(gè)由Object構(gòu)造的實(shí)例對(duì)象。

Foo.prototype.__proto__ === Object.prototype; // true

prototype屬性很特殊,它還有一個(gè)隱式的constructor,指向了構(gòu)造函數(shù)本身。

Foo.prototype.constructor === Foo; // true
a.constructor === Foo; // true
a.constructor === Foo.prototype.constructor; // true

PS: a.constructor屬性并不屬于aa.hasOwnProperty("constructor") === false),而是讀取的a.__proto__.constructor,所以上圖用虛線表示a.constructor,方便理解。

原型鏈

概念:

原型鏈作為實(shí)現(xiàn)繼承的主要方法,其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。
每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象(prototype),原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針(constructor),而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針(__proto__)。

那么,假如我們讓原型對(duì)象等于另一個(gè)類型的實(shí)例,此時(shí)的原型對(duì)象將包含一個(gè)指向另一個(gè)原型的指針,相應(yīng)地,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。假如另一個(gè)原型又是另一個(gè)類型的實(shí)例,那么上述關(guān)系依然成立。如此層層遞進(jìn),就構(gòu)造了實(shí)例與原型的鏈條,這就是原型鏈的基本概念。

意義:“原型鏈”的作用在于,當(dāng)讀取對(duì)象的某個(gè)屬性時(shí),JavaScript引擎先尋找對(duì)象本身的屬性,如果找不到,就到它的原型去找,如果還是找不到,就到原型的原型去找。以此類推,如果直到最頂層的Object.prototype還是找不到,則返回undefine。

親子鑒定

在JavaScript中,也存在鑒定親子之間DNA關(guān)系的方法:

instanceof 運(yùn)算符返回一個(gè)布爾值,表示一個(gè)對(duì)象是否由某個(gè)構(gòu)造函數(shù)創(chuàng)建。

Object.isPrototypeOf() 只要某個(gè)對(duì)象處在原型鏈上,isProtypeOf都返回true

var Bar = function() {}
var b = new Bar();
b instanceof Bar // true
Bar.prototype.isPrototypeOf(b) // true
Object.prototype.isPrototypeOf(Bar) // true

要注意,實(shí)例b的原型是Bar.prototype而不是Bar

一張歷史悠久的圖

這是一張描述了ObjectFunction以及一個(gè)函數(shù)實(shí)例Foo他們之間原型之間聯(lián)系。如果理解了上面的概念,這張圖是不難讀懂。

從上圖中,能看到一個(gè)有趣的地方。

Function.prototype.__proto__ 指向了 Object.prototype,這說(shuō)明Function.prototype 是一個(gè) Object實(shí)例,那么應(yīng)當(dāng)是先有的Object再有Function。

但是Object.prototype.constructor.__proto__ 又指向了 Function.prototype。這樣看來(lái),沒(méi)有FunctionObject也不能創(chuàng)建實(shí)例。

這就產(chǎn)生了一種類「先有雞還是先有蛋」的經(jīng)典問(wèn)題,到底是先有的Object還是先有的Function呢?
這么哲學(xué)向的問(wèn)題,留給你思考了。

我只是感慨:越往JavaScript的深處探索,越覺(jué)得這一門語(yǔ)言很哲學(xué)。

先有雞還是先有蛋?

update on 2017/01/05

時(shí)隔半年,偶爾翻開(kāi)這篇文章。
對(duì)于這個(gè)問(wèn)題,又有了新的思考。
愿意跟能看到這里的你來(lái)分享一下。

我們可以先把 Object.prototypeFunction.prototype 這兩個(gè)拎出來(lái)看,因?yàn)樗麄儽旧砭褪且粋€(gè)實(shí)例對(duì)象。
為方便理解,我們改一下名字,避免和 Object 和 Function 的強(qiáng)關(guān)聯(lián),分別叫:OpFp

那么就有這樣的原型鏈存在了

我再描述一下上面的原型鏈,先有 null , 再有了 Op , 然后再有了 Fp ,然后以 Fp 為原型的兩個(gè)構(gòu)造函數(shù) (Object, Function) 出現(xiàn)了。
而作為構(gòu)造函數(shù),需要有個(gè) prototype 屬性用來(lái)作為以該構(gòu)造函數(shù)創(chuàng)造的實(shí)例的繼承。
所以O(shè)bject.prototype = Op, Function.prototype = Fp。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79804.html

相關(guān)文章

  • JS程序

    摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開(kāi)始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊?,否則只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • javascript高級(jí)程序設(shè)計(jì)》第六章 讀書(shū)筆記 之 javascript繼承的6種方法

    摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...

    孫吉亮 評(píng)論0 收藏0
  • 理解JavaScript的核心知識(shí)點(diǎn):原型

    摘要:首先,需要來(lái)理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過(guò)程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來(lái)都被眾多開(kāi)發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒(méi)有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來(lái)越多的開(kāi)發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開(kāi)發(fā)者來(lái)說(shuō) J...

    iKcamp 評(píng)論0 收藏0
  • JS對(duì)象(1)重新認(rèn)識(shí)面向?qū)ο?/b>

    摘要:對(duì)象重新認(rèn)識(shí)面向?qū)ο竺嫦驅(qū)ο髲脑O(shè)計(jì)模式上看,對(duì)象是計(jì)算機(jī)抽象現(xiàn)實(shí)世界的一種方式。除了字面式聲明方式之外,允許通過(guò)構(gòu)造器創(chuàng)建對(duì)象。每個(gè)構(gòu)造器實(shí)際上是一個(gè)函數(shù)對(duì)象該函數(shù)對(duì)象含有一個(gè)屬性用于實(shí)現(xiàn)基于原型的繼承和共享屬性。 title: JS對(duì)象(1)重新認(rèn)識(shí)面向?qū)ο? date: 2016-10-05 tags: JavaScript 0x00 面向?qū)ο?從設(shè)計(jì)模式上看,對(duì)象是...

    superw 評(píng)論0 收藏0
  • 前端空間 - 收藏集 - 掘金

    摘要:封裝手寫的方筆記使用檢測(cè)文件前端掘金副標(biāo)題可以做什么以及使用中會(huì)遇到的坑。目的是幫助人們用純中文指南實(shí)現(xiàn)復(fù)選框中多選功能前端掘金作者緝熙簡(jiǎn)介是推出的一個(gè)天挑戰(zhàn)。 深入理解 JavaScript Errors 和 Stack Traces - 前端 - 掘金譯者注:本文作者是著名 JavaScript BDD 測(cè)試框架 Chai.js 源碼貢獻(xiàn)者之一,Chai.js 中會(huì)遇到很多異常處理...

    you_De 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<