摘要:對象重新認(rèn)識面向?qū)ο竺嫦驅(qū)ο髲脑O(shè)計模式上看,對象是計算機(jī)抽象現(xiàn)實(shí)世界的一種方式。除了字面式聲明方式之外,允許通過構(gòu)造器創(chuàng)建對象。每個構(gòu)造器實(shí)際上是一個函數(shù)對象該函數(shù)對象含有一個屬性用于實(shí)現(xiàn)基于原型的繼承和共享屬性。
title: JS對象(1)重新認(rèn)識面向?qū)ο?
date: 2016-10-05
tags: JavaScript
從設(shè)計模式上看,對象是計算機(jī)抽象現(xiàn)實(shí)世界的一種方式。
面向?qū)ο缶幊?object-oriented programming)的最主要目的是提高程序的重復(fù)使用性。
我們說,對象具有屬性(property)和方法(function),(其實(shí)本質(zhì)上方法也是一種屬性)在面向?qū)ο蟮脑O(shè)計模式中,屬性是一種描述,描述對象的狀態(tài),比如一個人一天 24 小時的情緒,每個時刻他的情緒都具有不同的狀態(tài),喜怒哀樂,抑郁癲狂,貪嗔癡念,當(dāng)然情緒只是生而為人的眾多狀態(tài)中的一種而已。而對象中的方法是一種功能,它的功能就是操作對象的屬性。比如,吃飯可以改變一個人的狀態(tài),對吃貨而已,吃飽以后會覺得特別幸福,吃飯是一種功能,它改變了一個人的情緒,讓人覺得幸福。
那么,反過來細(xì)想,人是一個對象,它具有情緒,他還要吃飯。所以可以說,對象是對屬性和方法的一種封裝。
0x01 南拳北腿對象中的幾個概念:
一切事物皆對象
對象具有封裝和繼承特性
對象與對象之間使用消息通信,各自存在消息隱藏
然而,面向?qū)ο髢H僅是一個概念或者編程思想而已,它不應(yīng)該依賴于某個語言存在。比如 Java 采用面向?qū)ο笏枷霕?gòu)造其語言,它實(shí)現(xiàn)了類、繼承、派生、多態(tài)、接口等機(jī)制。但是這些機(jī)制,只是實(shí)現(xiàn)面向?qū)ο缶幊痰囊环N手段,而非必須。換言之,一門語言可以根據(jù)其自身特性選擇合適的方式來實(shí)現(xiàn)面向?qū)ο蟆?/p>
JavaScript 語言是通過一種叫做原型(prototype) 的方式來實(shí)現(xiàn)面向?qū)ο缶幊痰摹?/p>
所以無論是基于類的(class-based)面向?qū)ο?/strong>,還是?基于原型的 (prototype-based) 面向?qū)ο?/strong> 也都只是為實(shí)現(xiàn)面向?qū)ο筮@一理念在構(gòu)造客觀世界的兩種不同方式而已。
0x02 類 or 原型在基于類的面向?qū)ο蠓绞街校?strong>對象(object) 依靠 類(class) 來產(chǎn)生。而在基于原型的面向?qū)ο蠓绞街校?strong>對象(object) 則是依靠 構(gòu)造器(constructor) 利用 原型(prototype) 構(gòu)造出來的。
而關(guān)于這兩種方式誰更為徹底地表達(dá)了面向?qū)ο蟮乃枷?,目前尚有爭論?/p>
類是一個抽象概念而并非實(shí)體,而對象的產(chǎn)生是一個實(shí)體的產(chǎn)生;
原型方式中的構(gòu)造器 (constructor) 和原型 (prototype) 本身是其他對象通過原型方式構(gòu)造出來的對象。
在類式面向?qū)ο笳Z言中,對象的狀態(tài) (state) 由對象實(shí)例 (instance) 所持有,對象的行為方法 (method) 則由聲明該對象的類所持有,并且只有對象的結(jié)構(gòu)和方法能夠被繼承;而在原型式面向?qū)ο笳Z言中,對象的行為、狀態(tài)都屬于對象本身,并且能夠一起被繼承。
0x03 JavaScript 中的面向?qū)ο?/b>JavaScript 是一種基于原型的編程語言,并沒有 class 語句,而是把函數(shù)用作類。當(dāng)然,ES6 提供了 class 的語法糖
ECMAScript 是一門徹底的面向?qū)ο蟮木幊陶Z言,JavaScript 是其中的一個變種 (variant)。它提供了 6 種基本數(shù)據(jù)類型,即 Boolean、Number、String、Null、Undefined、Object。為了實(shí)現(xiàn)面向?qū)ο螅?em>ECMAScript設(shè)計出了一種非常成功的數(shù)據(jù)結(jié)構(gòu) - JSON(JavaScript Object Notation), 這一經(jīng)典結(jié)構(gòu)已經(jīng)可以脫離語言而成為一種廣泛應(yīng)用的數(shù)據(jù)交互格式。
ECMAScript除了字面式聲明(literal notation) 方式之外, 允許通過構(gòu)造器(constructor) 創(chuàng)建對象。每個構(gòu)造器實(shí)際上是一個函數(shù)(function) 對象, 該函數(shù)對象含有一個prototype屬性用于實(shí)現(xiàn)基于原型的繼承(prototype-based inheritance) 和共享屬性(shared properties)。對象可以由 “new 關(guān)鍵字 + 構(gòu)造器調(diào)用” 方式來創(chuàng)建。
但需要指出的是,這與java語言的new含義毫無關(guān)系,因?yàn)槠鋵ο髽?gòu)造的機(jī)理完全不同。ECMAScript 完全可以用其它非new表達(dá)式來用調(diào)用構(gòu)造器創(chuàng)建對象。
0x04 原型鏈涉及到繼承這一塊,Javascript 只有一種結(jié)構(gòu),那就是:對象。在 javaScript 中,每個對象都有一個指向它的原型對象(prototype)的內(nèi)部屬性_proto_屬性。而這個原型對象又有自己的原型,直到某個對象的原型為 null 為止(也就是不再有原型指向),組成這條鏈的最后一環(huán)。這種一級一級的鏈結(jié)構(gòu)就稱為原型鏈(prototype chain)。
一張經(jīng)典的 JavaScript 原型鏈圖可以揭示一切:
要理解上圖,只需要搞明白兩個屬性(指針)的區(qū)別,即是_proto_ 屬性和 prototype 屬性。
每個構(gòu)造函數(shù)都有一個 prototype 屬性,該屬性是一個指針,指向該構(gòu)造函數(shù)的原型。
而實(shí)例中包含一個屬性 _proto_ 屬性,該屬性是一個指針,指向該實(shí)例所屬的構(gòu)造函數(shù)創(chuàng)建的原型。
不同的瀏覽器對實(shí)例中的 _proto_ 屬性表示不同。
每創(chuàng)建一個構(gòu)造函數(shù)便會相應(yīng)的創(chuàng)建一個與其相對應(yīng)的原型對象(由構(gòu)造函數(shù)創(chuàng)建出來的原型對象,JS 引擎自動創(chuàng)建)。
在默認(rèn)情況下,構(gòu)造函數(shù)創(chuàng)建的原型對象都會有一個 constructor 屬性,而這個屬性指向 prototype 屬性所在的那個函數(shù)。
所以,我們可以得出一個結(jié)論,構(gòu)造函數(shù)的 prototype 和由該構(gòu)造函數(shù)創(chuàng)建的實(shí)例的 _proto_ 指向的是內(nèi)存中的的同一塊地址,也正是如此,才使得在原型中定義的方法和屬性具有共享的基礎(chǔ)。
有了?原型鏈,便可以定義一種所謂的?屬性隱藏機(jī)制,并通過這種機(jī)制實(shí)現(xiàn)繼承。ECMAScript 規(guī)定,當(dāng)要給某個對象的屬性賦值時,解釋器會查找該對象原型鏈中第一個含有該屬性的對象(注:原型本身就是一個對象,那么原型鏈即為一組對象的鏈。對象的原型鏈中的第一個對象是該對象本身)進(jìn)行賦值。
所以,當(dāng)試圖訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依此層層向上搜索,直到找到一個名字匹配的屬性或到達(dá)原型鏈的末尾。
0x05 JavaScript 的類式繼承實(shí)現(xiàn)基于原型的繼承方式,雖然實(shí)現(xiàn)了代碼復(fù)用,但其行文松散且不夠流暢,可閱讀性差,不利于實(shí)現(xiàn)擴(kuò)展和對源代碼進(jìn)行有效地組織管理。不得不承認(rèn),類式繼承方式在語言實(shí)現(xiàn)上更具健壯性,且在構(gòu)建可復(fù)用代碼和組織架構(gòu)程序方面具有明顯的優(yōu)勢。
0x06 JavaScript 私有成員實(shí)現(xiàn)JavaScript 沒有實(shí)現(xiàn)面向?qū)ο笾械男畔㈦[藏,即私有和公有。與其他類式面向?qū)ο竽菢语@式地聲明私有公有成員的方式不同,JavaScript 的信息隱藏就是靠閉包實(shí)現(xiàn)的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/86518.html
摘要:前言我們在深入淺出面向?qū)ο蠛驮透拍钇谶@篇文章中了解到了如何使用解決重復(fù)創(chuàng)建浪費(fèi)內(nèi)存的問題,其中的關(guān)鍵就是,那么這篇文章讓我們來重新了解的前世今生一個苦逼年級主任的故事開學(xué)啦高一年級主任龔主任需要為全年級每一位理科班新生錄入學(xué)號并為每一位 前言 我們在深入淺出面向?qū)ο蠛驮汀靖拍钇?】在這篇文章中了解到了如何使用new Function解決重復(fù)創(chuàng)建浪費(fèi)內(nèi)存的問題,其中的關(guān)鍵就是new...
摘要:方法即為收集器,它接收高階函數(shù)和的后端掘金年的第一天,我坐在獨(dú)墅湖邊,寫下這篇文章。正因如此,所以最全系列教程后端掘金是從版本開始引入的一個新的,可以替代標(biāo)準(zhǔn)的。 設(shè)計模式之單例模式 - 掘金前言 作為一個好學(xué)習(xí)的程序開發(fā)者,應(yīng)該會去學(xué)習(xí)優(yōu)秀的開源框架,當(dāng)然學(xué)習(xí)的過程中不免會去閱讀源碼,這也是一個優(yōu)秀程序員的必備素養(yǎng),在學(xué)習(xí)的過程中很多人會遇到的障礙,那就是設(shè)計模式。很多優(yōu)秀的框架會運(yùn)...
摘要:設(shè)計模式的定義在面向?qū)ο筌浖O(shè)計過程中針對特定問題的簡潔而優(yōu)雅的解決方案。從前由于使用的局限性,和做的應(yīng)用相對簡單,不被重視,就更談不上設(shè)計模式的問題。 ‘從大處著眼,從小處著手’,以前對這句話一知半解,自從踏出校門走入社會,開始工作以來,有了越來越深的理解,偶有發(fā)現(xiàn)這句話用在程序開發(fā)中也有用,所以,近段時間開始嘗試著分析jQuery源碼,分析angularjs源碼,學(xué)習(xí)設(shè)計模式。 設(shè)...
摘要:此時,鏈家起到的作用就是代理的作用。驗(yàn)證代理構(gòu)造函數(shù)第二個參數(shù)中的方法,可以很方便的驗(yàn)證向一個對象的傳值。 1 什么是代理模式 showImg(https://segmentfault.com/img/remote/1460000015800706?w=1262&h=464); 為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理...
閱讀 3700·2023-04-26 02:55
閱讀 2926·2021-11-02 14:38
閱讀 4230·2021-10-21 09:39
閱讀 2923·2021-09-27 13:36
閱讀 4064·2021-09-22 15:08
閱讀 2746·2021-09-08 10:42
閱讀 2875·2019-08-29 12:21
閱讀 752·2019-08-29 11:22