日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript为什么使用原型模式而不是类模式

發(fā)布時(shí)間:2025/4/16 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript为什么使用原型模式而不是类模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

導(dǎo)言: 作為JavaScript初學(xué)者的本菜雞而言,剛一開始接觸這門語言我就被他的原型模式給嚇到了。并且在相當(dāng)長(zhǎng)的一段時(shí)間之內(nèi),我都完全不能理解或者不能接受這個(gè)模式。直到最近經(jīng)過多方調(diào)查和思考才有所明悟。本篇文章就來記錄一下我對(duì)JavaScript為什么使用原型模式而不是用類模式這個(gè)問題的一點(diǎn)看法。

為什么是原型模式面向?qū)ο?/h3>

是啊,為什么是原型模式呢?類模式那么的優(yōu)雅,那么容易理解,當(dāng)今世界扛把子級(jí)別的語言無論是c++,Java還是Python等,全部都是基于類的面向?qū)ο蟆;陬惖拿嫦驅(qū)ο缶皖愃朴阼T模和鑄件的關(guān)系。我們精心維護(hù)好這樣的鑄模,然后生成一堆的鑄件,這些鑄件就可以愉快的運(yùn)行在各行各業(yè),起到相應(yīng)的功能。當(dāng)鑄件出了一些問題之后沒有關(guān)系,我重新在用鑄模搞出一個(gè)鑄件就可以了。也有可能鑄模跟不上時(shí)代的發(fā)展了,也沒有關(guān)系,我重新調(diào)整一下鑄模的結(jié)構(gòu),這樣以后就能生產(chǎn)出緊跟行業(yè)最新需求的鑄件了。基于類的面向?qū)ο笫嵌嗝吹暮冒?#xff0c;有了它我們就可以建設(shè)美麗新世界了!

甚至我一度以為,面向?qū)ο缶褪侵傅幕陬惖拿嫦驅(qū)ο蟆V钡轿矣龅搅诵皭旱腏avaScript,一下子讓我三觀盡碎!

不過我還是存有一點(diǎn)僥幸心理,或許可能是那個(gè)JavaScript設(shè)計(jì)者設(shè)計(jì)這門語言時(shí)間過于倉促,沒有考慮到基于類的面向?qū)ο筮@種設(shè)計(jì)是多么優(yōu)雅,直到我后來讀到下面這段內(nèi)容:

在Brendan Eich為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)時(shí),借鑒了Self和Smalltalk這兩門基于原型的語言。之所以選擇基于原型的面向?qū)ο?#xff0c;不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來相對(duì)簡(jiǎn)單,而是因?yàn)閺囊婚_始Brendan Eich就沒有打算在JavaScript中加入類的概念。

蒼天啊!JavaScript居然沒有類的概念。到了ES6出了class關(guān)鍵字之后,也不過是基于原型的一種語法糖。可是你都沒有類了,為什么還要搞new關(guān)鍵字,簡(jiǎn)直是脫褲子放屁。后來我又讀到一段話:

然而很不幸,因?yàn)橐恍┕菊卧?#xff0c;JavaScript 推出之時(shí)受管理層之命被要求模仿 Java,所以,JavaScript 創(chuàng)始人 Brendan Eich 在“原型運(yùn)行時(shí)”的基礎(chǔ)上引入了 new、 this 等語言特性,使之“看起來更像 Java”。

好吧!不管怎么說,就是基于原型了。但是為什么要選原型呢?下面談?wù)勎业睦斫狻?/p>

我想設(shè)計(jì)模式的差異可能是因?yàn)榍岸撕秃蠖嗣媾R的情況不太一樣。對(duì)于在服務(wù)端運(yùn)行的程序而言,更應(yīng)該追求穩(wěn)定性。而在客戶端運(yùn)行的程序,經(jīng)常要面臨和用戶交互、渲染等任務(wù),動(dòng)態(tài)性的成分更多一些。因此服務(wù)端的程序使用基于類的面向?qū)ο?#xff0c;走鑄模、鑄件路線。我們做修改基本只改模具,不要鑄件發(fā)揮自己的主觀能動(dòng)性。比如你在寫Python或者Java程序的時(shí)候,你生成實(shí)例化對(duì)象之后,很少會(huì)要求對(duì)象變來變?nèi)グ伞?/p>

而JavaScript希望對(duì)象盡可能發(fā)揮自己的主觀能動(dòng)性,干脆直接把模具扔了。玩起了原型模式和原型繼承。沒有模具那該如何搞對(duì)象呢?這個(gè)我們后面會(huì)講到,首先來看一下JavaScript對(duì)象的主觀能動(dòng)性吧。

let o = {a: 1 }o.b = 2console.log(o)

因?yàn)镴avaScript沒有類的束縛,所以對(duì)象可以盡情的添加屬性(在Java語言中,我們將類中的函數(shù)稱為方法,但是JavaScript只有屬性沒有方法這種叫法,函數(shù)也是一種屬性),對(duì)于上述代碼,寫成添加函數(shù)這樣的形式也沒有問題:

o.b = function() {console.log('haha') }

你可以看看o的輸出結(jié)果。如果是用class約束一下呢?或者class真的約束的了嗎?

class Animal {constructor(name) {this.name = name}getName() {return this.name} }let dog = new Animal('dog') console.log(dog.getName())dog.bark = function() {console.log('wangwang') } console.log(dog.bark())

可以看一下輸出結(jié)果。這是Javascript基于原型的靈活性。此外,可能是為了進(jìn)一步增加靈活性吧,JavaScript還增加了訪問器屬性。

let o = {get a() {return 1} }console.log(o.a)

訪問器屬性跟數(shù)據(jù)屬性不同,每次訪問屬性都會(huì)執(zhí)行 getter 或者 setter 函數(shù)。這樣我們每次訪問a屬性時(shí)都會(huì)有對(duì)應(yīng)的輸出。(有沒有一種proxy的感覺?)

原型模式特點(diǎn)

正是基于原型的靈活性,所以JavaScript選擇了原型模式而沒有使用類對(duì)象模式。接下來我們來看一下原型模式的特點(diǎn)。

前面我們提到,基于類的面向?qū)ο罂梢员茸鳛殍T模和鑄件的關(guān)系,我們更關(guān)注與模具而不是鑄件。我想了半天,沒有想到一個(gè)十分形象和恰當(dāng)?shù)谋扔?#xff0c;有一個(gè)不太恰當(dāng)?shù)摹?梢詫⒃瓦@種模式比作吸血鬼發(fā)展新的吸血鬼。為什么這樣比喻呢?上面我們舉例子也提到了,原型模式希望我們更加關(guān)注對(duì)象,而不是模具。那么每一個(gè)吸血鬼都有自己的充分主觀能動(dòng)性。比如電影《暮光之城》中的吸血鬼,還可以轟轟烈烈的談戀愛,撒狗糧。但是對(duì)于工廠生產(chǎn)的鑄件而言,比較類似于僵尸,沒有辦法很好發(fā)揮對(duì)象的主觀能動(dòng)性。(比如類似于僵尸沒有理智,而吸血鬼有比較強(qiáng)的理智)

如何創(chuàng)建一個(gè)新的對(duì)象呢?答案是通過對(duì)象克隆的方式。而不是通過類實(shí)例化對(duì)象的方式。(比如類似于每一個(gè)有充分主觀能動(dòng)性的吸血鬼,咬人之后就會(huì)發(fā)展出一個(gè)新的吸血鬼),需要注意的是,我們不要被new關(guān)鍵字所迷惑了,以為是通過類實(shí)例化對(duì)象的方式來創(chuàng)建新的對(duì)象。比如下面代碼:

let obj1 = new Object() // 或者是寫成這樣 let obj2 = {}

引擎內(nèi)部都會(huì)從Object.prototype上面克隆出來一個(gè)對(duì)象,我們最終得到的就是這樣克隆出來的一個(gè)對(duì)象。還是舉吸血鬼的例子,就是讓Object這個(gè)吸血鬼,咬了一個(gè)人,然后這個(gè)人就變成了有Object屬性的吸血鬼了。這個(gè)新的吸血鬼可能也會(huì)去談戀愛,總之是具有很高的主觀能動(dòng)性的。

關(guān)于new關(guān)鍵字我再展開說一下,當(dāng)一個(gè)對(duì)象被new關(guān)鍵字修飾的時(shí)候,會(huì)首先調(diào)用這個(gè)對(duì)象的構(gòu)造函數(shù),也就是constructor。我們要是普通對(duì)象,是不是就不能克隆出對(duì)象呢?答案不是這樣,還可以使用Object.create(),每一個(gè)吸血鬼都可以發(fā)揮自身特點(diǎn),克隆出一個(gè)新的吸血鬼。

let cat = {say() {console.log('miao-miao')} }let anotherCat = Object.create(cat)

需要注意的是,你不能寫成這樣

let anotherCat = cat

這句話的意思是把a(bǔ)notherCat指向cat的內(nèi)存地址。而不是復(fù)制。

參考資料

[1] 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)戰(zhàn)》

總結(jié)

以上是生活随笔為你收集整理的JavaScript为什么使用原型模式而不是类模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。