91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript是面向對象還是基于對象

發布時間:2021-11-06 15:31:15 來源:億速云 閱讀:112 作者:iii 欄目:web開發

這篇文章主要講解了“JavaScript是面向對象還是基于對象”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JavaScript是面向對象還是基于對象”吧!

什么是對象?

我們先來說說什么是對象,因為翻譯的原因,中文語境下我們很難理解“對象”的真正含義。事實上,Object(對象)在英文中,是一切事物的總稱,這和面向對象編程的抽象思維有互通之處。中文的“對象”卻沒有這樣的普適性,我們在學習編程的過程中,更多是把它當作一個專業名詞來理解。

但不論如何,我們應該認識到,對象并不是計算機領域憑空造出來的概念,它是順著人類思維模式產生的一種抽象(于是面向對象編程也被認為是:更接近人類思維模式的一種編程范式)。

那么,我們先來看看在人類思維模式下,對象究竟是什么。

JavaScript是面向對象還是基于對象

對象這一概念在人類的幼兒期形成,這遠遠早于我們編程邏輯中常用的值、過程等概念。在幼年期,我們總是先認識到某一個蘋果能吃(這里的某一個蘋果就是一個對象),繼而認識到所有的蘋果都可以吃(這里的所有蘋果,就是一個類),再到后來我們才能意識到三個蘋果和三個梨之間的聯系,進而產生數字“3”(值)的概念。

在《面向對象分析與設計》這本書中,Grady Booch 替我們做了總結,他認為,從人類的認知角度來說,對象應該是下列事物之一:

  • 一個可以觸摸或者可以看見的東西;

  • 人的智力可以理解的東西;

  • 可以指導思考或行動(進行想象或施加動作)的東西。

有了對象的自然定義后,我們就可以描述編程語言中的對象了。在不同的編程語言中,設計者也利用各種不同的語言特性來抽象描述對象,最為成功的流派是使用“類”的方式來描述對象,這誕生了諸如 C++、Java 等流行的編程語言。而 JavaScript 早年卻選擇了一個更為冷門的方式:原型。這是我在前面說它不合群的原因之一。

JavaScript是面向對象還是基于對象

然而很不幸,因為一些公司政治原因,JavaScript 推出之時受管理層之命被要求模仿 Java,所以,JavaScript 創始人 Brendan Eich 在“原型運行時”的基礎上引入了 new、this 等語言特性,使之“看起來更像 Java”。

在 ES6 出現之前,大量 JavaScript 程序員試圖在原型體系的基礎上,把 JavaScript 變得更像是基于類的編程,進而產生了很多所謂的“框架”,比如 PrototypeJS、Dojo。事實上,它們成為了某種 JavaScript 的古怪方言,甚至產生了一系列互不相容的社群,顯然這樣做的收益遠遠小于損失。

如果我們從運行時角度來談論對象,就是在討論 JavaScript 實際運行中的模型,這是由于任何代碼執行都必定繞不開運行時的對象模型,不過,幸運的是,從運行時的角度看,可以不必受到這些“基于類的設施”的困擾,這是因為任何語言運行時類的概念都是被弱化的。

首先我們來了解一下 JavaScript 是如何設計對象模型的。

JavaScript 對象的特征

在我看來,不論我們使用什么樣的編程語言,我們都先應該去理解對象的本質特征(參考 Grandy Booch《面向對象分析與設計》)。總結來看,對象有如下幾個特點。

  • 對象具有唯一標識性:即使完全相同的兩個對象,也并非同一個對象。

  • 對象有狀態:對象具有狀態,同一對象可能處于不同狀態下。

  • 對象具有行為:即對象的狀態可能因為它的行為產生變遷。

我們先來看第一個特征,對象具有唯一標識性。一般而言,各種語言的對象唯一標識性都是用內存地址來體現的,所以,JavaScript 程序員都知道,任何不同的 JavaScript 對象其實是互不相等,我們可以看下面的代碼,o1 和 o2 初看是兩個一模一樣的對象,但是打印出來的結果卻是 false。

var o1 = { a: 1 };
var o2 = { a: 1 };
console.log(o1 == o2); // false

關于對象的第二個和第三個特征“狀態和行為”,不同語言會使用不同的術語來抽象描述它們,比如 C++ 中稱它們為“成員變量”和“成員函數”,Java 中則稱它們為“屬性”和“方法”。

在 JavaScript 中,將狀態和行為統一抽象為“屬性”,考慮到 JavaScript 中將函數設計成一種特殊對象(關于這點,我會在后文中詳細講解,此處先不用細究),所以 JavaScript 中的行為和狀態都能用屬性來抽象。

下面這段代碼其實就展示了普通屬性和函數作為屬性的一個例子,其中 o 是對象,d 是一個屬性,而函數 f 也是一個屬性,盡管寫法不太相同,但是對 JavaScript 來說,d 和 f 就是兩個普通屬性。

var o = { 
 d: 1,
 f() {
 console.log(this.d);
 } 
};

所以,總結一句話來看,在 JavaScript 中,對象的狀態和行為其實都被抽象為了屬性。如果你用過 Java,一定不要覺得奇怪,盡管設計思路有一定差別,但是二者都很好地表現了對象的基本特征:標識性、狀態和行為。

在實現了對象基本特征的基礎上, 我認為,JavaScript 中對象獨有的特色是:對象具有高度的動態性,這是因為 JavaScript 賦予了使用者在運行時為對象添改狀態和行為的能力。

我來舉個例子,比如,JavaScript 允許運行時向對象添加屬性,這就跟絕大多數基于類的、靜態的對象設計完全不同。如果你用過 Java 或者其它別的語言,肯定會產生跟我一樣的感受。

下面這段代碼就展示了運行時如何向一個對象添加屬性,一開始我定義了一個對象 o,定義完成之后,再添加它的屬性 b,這樣操作,是完全沒問題的。這一點你要理解。

var o = { a: 1 };
o.b = 2;
console.log(o.a, o.b); //1 2

為了提高抽象能力,JavaScript 的屬性被設計成比別的語言更加復雜的形式,它提供了數據屬性和訪問器屬性(getter/setter)兩類。

JavaScript 對象的兩類屬性

對 JavaScript 來說,屬性并非只是簡單的名稱和值,JavaScript 用一組特征(attribute)來描述屬性(property)。

先來說第一類屬性,數據屬性。它比較接近于其它語言的屬性概念。數據屬性具有四個特征。

  • value:就是屬性的值。

  • writable:決定屬性能否被賦值。

  • enumerable:決定 for in 能否枚舉該屬性。

  • configurable:決定該屬性能否被刪除或者改變特征值。

在大多數情況下,我們只關心數據屬性的值即可。

第二類屬性是訪問器(getter/setter)屬性,它也有四個特征。

  • getter:函數或 undefined,在取屬性值時被調用。

  • setter:函數或 undefined,在設置屬性值時被調用。

  • enumerable:決定 for in 能否枚舉該屬性。

  • configurable:決定該屬性能否被刪除或者改變特征值。

訪問器屬性使得屬性在讀和寫時執行代碼,它允許使用者寫入和讀出屬性時得到完全不同的值,它可以視為一種函數的語法糖。

我們通常用于定義屬性的代碼會產生數據屬性,其中的 writable、enumerable、configurable 都默認為 true。我們可以使用內置函數 Object.getOwnPropertyDescripter 來查看,如以下代碼所示:

var o = { a: 1 };
o.b = 2;
//a 和 b 皆為數據屬性
Object.getOwnPropertyDescriptor(o,"a") // {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(o,"b") // {value: 2, writable: true, enumerable: true, configurable: true}

我們在這里使用了兩種語法來定義屬性,定義完屬性后,我們用 JavaScript 的 API 來查看這個屬性,我們可以發現,這樣定義出來的屬性都是數據屬性,writeable、enumerable、configurable 都是默認值為 true。

如果我們要想改變屬性的特征,或者定義訪問器屬性,可以使用 Object.defineProperty,示例如下:

var o = { a: 1 };
Object.defineProperty(o, "b", {value: 2, writable: false, enumerable: false, configurable: true});
//a 和 b 都是數據屬性,但特征值變化了
Object.getOwnPropertyDescriptor(o,"a"); // {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(o,"b"); // {value: 2, writable: false, enumerable: false, configurable: true}
o.b = 3;
console.log(o.b); // 2

這里我們使用了 Object.defineProperty 來定義屬性,這樣定義屬性可以改變屬性的 writable 和 enumerable,我們同樣用 Object.getOwnPropertyDescriptor 來查看,發現確實改變了 writable 和 enumerable 特征。因為 writable 特征為 false,所以我們重新對 b 賦值,b 的值不會發生變化。

在創建對象時,也可以使用 get 和 set 關鍵字來創建訪問器屬性,代碼如下所示:

var o = { get a() { return 1 } };
 
console.log(o.a); // 1

訪問器屬性跟數據屬性不同,每次訪問屬性都會執行 getter 或者 setter 函數。這里我們的 getter 函數返回了 1,所以 o.a 每次都得到 1。

這樣,我們就理解了,實際上 JavaScript 對象的運行時是一個“屬性的集合”,屬性以字符串或者 Symbol 為 key,以數據屬性特征值或者訪問器屬性特征值為 value。對象是一個屬性的索引結構(索引結構是一類常見的數據結構,我們可以把它理解為一個能夠以比較快的速度用 key 來查找 value 的字典)。我們以上面的對象 o 為例,你可以想象一下“a”是 key。

這里{writable:true,value:1,configurable:true,enumerable:true}是 value。我們在前面的類型課程中,已經介紹了 Symbol 類型,能夠以 Symbol 為屬性名,這是 JavaScript 對象的一個特色。

講到了這里,如果你理解了對象的特征,也就不難理解我開篇提出來的問題。

你甚至可以理解為什么會有“JavaScript 不是面向對象”這樣的說法:JavaScript 的對象設計跟目前主流基于類的面向對象差異非常大。而事實上,這樣的對象系統設計雖然特別,但是 JavaScript 提供了完全運行時的對象系統,這使得它可以模仿多數面向對象編程范式,所以它也是正統的面向對象語言。

JavaScript 語言標準也已經明確說明,JavaScript 是一門面向對象的語言,我想標準中能這樣說正因為 JavaScript 的高度動態性的對象系統。

所以,我們應該在理解其設計思想的基礎上充分挖掘它的能力,而不是機械地模仿其它語言。

要想理解 JavaScript 對象,必須清空我們腦子里“基于類的面向對象”相關的知識,回到人類對對象的樸素認知和面向對象的語言無關基礎理論,我們就能夠理解 JavaScript 面向對象設計的思路。

很多人在思考 JavaScript 對象時,會帶著已有的“對象”觀來看問題,最后的結果當然就是“剪不斷理還亂”了。

感謝各位的閱讀,以上就是“JavaScript是面向對象還是基于對象”的內容了,經過本文的學習后,相信大家對JavaScript是面向對象還是基于對象這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

忻城县| 肃宁县| 扎兰屯市| 高州市| 勐海县| 凭祥市| 四川省| 修武县| 通化市| 阜康市| 浠水县| 化隆| 台江县| 界首市| 闽清县| 麻栗坡县| 满洲里市| 郎溪县| 开封市| 云浮市| 金塔县| 米泉市| 拜城县| 莫力| 镇康县| 白朗县| 淮滨县| 龙岩市| 逊克县| 梁山县| 中西区| 孝昌县| 镇远县| 通化县| 贞丰县| 沈阳市| 额敏县| 集贤县| 鲁甸县| 新丰县| 林西县|