成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

sugarmo / 2453人閱讀

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

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

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

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

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

一切皆為對象

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

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

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

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

原型指針 __proto__

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

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

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

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

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

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

所以說,JavaScript中的對象,追根溯源都是來自一個(gè)null對象。佛曰:萬物皆空,善哉善哉。

除了使用.__proto__方式訪問對象的原型,還可以通過Object.getPrototypeOf方法來獲取對象的原型,以及通過Object.setPrototypeOf方法來重寫對象的原型。

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

原型對象 prototype

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

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

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

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

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

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è)原型對象(prototype),原型對象都包含一個(gè)指向構(gòu)造函數(shù)的指針(constructor),而實(shí)例都包含一個(gè)指向原型對象的內(nèi)部指針(__proto__)。

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

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

親子鑒定

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

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

Object.isPrototypeOf() 只要某個(gè)對象處在原型鏈上,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

一張歷史悠久的圖

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

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

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

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

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

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

先有雞還是先有蛋?

update on 2017/01/05

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

我們可以先把 Object.prototypeFunction.prototype 這兩個(gè)拎出來看,因?yàn)樗麄儽旧砭褪且粋€(gè)實(shí)例對象。
為方便理解,我們改一下名字,避免和 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 屬性用來作為以該構(gòu)造函數(shù)創(chuàng)造的實(shí)例的繼承。
所以O(shè)bject.prototype = Op, Function.prototype = Fp。

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79804.html

相關(guān)文章

  • JS程序

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

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

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

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

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

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

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

    superw 評論0 收藏0
  • 前端空間 - 收藏集 - 掘金

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

    you_De 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<