再談js對象數據結構底層實現原理-object array map set

若是有java基礎的同窗,能夠回顧下《再談Java數據結構—分析底層實現與應用注意事項》:java把內存分兩種:一種是棧內存,另外一種是堆內存。基本類型(即int,short,long,byte,float,double,boolean,char)在棧區分配空間,全部的對象都在堆(Heap)中分配空間。按照這思路來談下JavaScript。html

最新的 ECMAScript 標準定義了 7 種數據類型:前端

  • 6 種原始類型-基本數據類型(按值訪問)java

    • Null (js中的數據在底層是以二進制存儲,若是前三位爲0,那麼就會斷定爲object,而null的全部都爲0)es6

    • Undefinedweb

    • 基本包裝類型(自動建立的基本包裝類型的對象—非Boolean,Number, String內置函數new出來的,對象只存代碼的執行瞬間)算法

      • Number(基於 IEEE 754 標準的雙精度 64 位二進制格式的值——數字、±Infinity、NaN)數組

      • String  數據結構

      • Booleanapp

    • Symbol (ECMAScript 6 新定義,實例是惟一且不可改變的)數據結構和算法

  • 引用類型: Object(包括Object/Array/RegExp/Date/null)

任何一個JavaScript的標識、常量、變量和參數都只是unfined, null, bool, number, string,symbol,object 和 function類型中的一種,也就typeof返回值代表的類型。——推薦閱讀《細說 JavaScript 七種數據類型

js基本類型數據都是直接按值存儲在棧中的(Undefined、Null、不是new出來的布爾、數字和字符串),每種類型的數據佔用的內存空間的大小是肯定的,並由系統自動分配和自動釋放。這樣帶來的好處就是,內存能夠及時獲得回收,相對於堆來講   ,更加容易管理內存空間。java的基本數據類型共有8種,即int,short,long,byte,float,double,boolean,char(注意,並無String的基本類型 )

js引用類型數據被存儲於堆中 (如對象、數組、函數等,它們是經過拷貝和new出來的)。其實,說存儲於堆中,也不太準確,由於,引用類型的數據的地址指針是存儲於棧中的,當咱們想要訪問引用類型的值的時候,須要先從棧中得到對象的地址指針,而後,在經過地址指針找到堆中的所須要的數據。這個後講,首先咱們要搞清楚

js堆棧示意圖

數據在內存中的存儲結構,也就是物理結構,分爲兩種:順序存儲結構和鏈式存儲結構。

  • 順序存儲結構:是把數據元素存放在地址連續的存儲單元裏,其數據間的邏輯關係和物理關係是一致的。數組就是順序存儲結構的典型表明。

  • 鏈式存儲結構:是把數據元素存放在內存中的任意存儲單元裏,也就是能夠把數據存放在內存的各個位置。這些數據在內存中的地址能夠是連續的,也能夠是不連續的。鏈表就是順序存儲結構的典型表明。

和順序存儲結構不一樣的是,鏈式存儲結構的數據元素之間是經過指針來鏈接的,咱們能夠通使用指針來找到某個數據元素的位置,而後對這個數據元素進行一些操做。

數組和隊列均可以實現棧和鏈表。

打個比方說一下順序存儲結構和鏈式存儲結構的區別:

好比去銀行取錢,順序存儲結構就至關於,全部的客戶按照先來後到的順序有序的的坐在大廳的椅子上(注意:是有順序的坐着哦)。

而鏈式存儲結構至關於,全部的客戶只要一到銀行,大堂經理就給他們每人一個號碼,而後他們能夠隨便坐在哪一個椅子上(隨便坐,不須要按照什麼順序坐),只須要等待工做人員廣播叫號便可。

而每一個客戶手裏的號碼就至關於指針,當前的指針指向下一個存儲空間,這樣,全部不連續的空間就能夠被有順序的按照線性鏈接在一塊兒了。

什麼是堆(heap)、棧(stack)

各類語言在處理堆棧的原理上都大同小異。

  • 堆是動態分配內存,內存大小不一,也不會自動釋放

  • 棧是自動分配相對固定大小的內存空間,並由系統自動釋放。棧先進後出(LIFO,last in first out),隊列後進先出(FIFO,first in first out)。

  • 數組數據結構是由相同類型的元素(element)的集合所組成的數據結構,分配一塊連續的內存來存儲。利用元素的索引(index)能夠計算出該元素對應的存儲地址。數組尋址容易,插入和刪除困難的問題,而鏈表增刪容易,查找困難。棧能夠用數組或鏈表實現(c艹、java等基本功)。

  • 集合表示一組互不相同的元素(不重複的元素)。

  • 字典存儲的是[鍵,值]對,其中鍵名是用來查詢特定元素的。

計算機數據結構圖解

 

20190509204136601106478.png

經典的數據結構大概就那麼幾種,list、stack、queue、linkedList、dictionary、hash、set、tree、graph......

JavaScript數據結構

es5自帶的:array、object

es6自帶的:set map、weakset weakmap (強引用、弱引用,Set 和 Map 數據結構,)

es未有的:dictionary list linkedlist doublelinkedlist quene hash stack 

在JavaScript中無論多麼複雜的數據和代碼,均可以組織成object形式的對象

js裏面的object類型在C/C++/Java等語言是沒有這種數據類型(C是「萬物之母」,C裏面沒有的),就得經過某種方式實現,到底是如何實現其的?這個問題最早看了《從Chrome源碼看JS Object的實現》,而後再回顧以前看的《JavaScript 對象屬性底層原理》,在根據再談系列一向的文風總

 

對象大多數時候表現爲Dictionary:如:{a:'foo',b:'bar'}

  • 存儲結構能夠是數組也能夠是HashMap

  • 具備額外的輔助信息(存儲在描述符數組中)——數組索引屬性

數組索引屬性(元素):

如:數組['foo','bar']有兩個數組索引屬性:0,值爲'foo'; 1,值爲'bar'。

  • 存儲結構一般爲簡單的數組結構。但某些狀況下也會切換到Hash結構以節省內存。

  • 可使用鍵來推斷它們在屬性數組中的位置

數組索引屬性命名屬性存儲在兩個單獨的數據結構中:

V8裏面全部的數據類型的根父類都是Object,Object派生HeapObject,提供存儲基本功能,往下的JSReceiver用於原型查找,再往下的JSObject就是JS裏面的Object,Array/Function/Date等繼承於JSObject。左邊的FixedArray是實際存儲數據的地方。推薦看原文《從Chrome源碼看JS Object的實現

JS Object類圖

在建立一個JSObject以前,會先把讀到的Object的文本屬性序列化成constant_properties,以下的data:

var data = {
        name: "yin",
        age: 18,
        "-school-": "high school"
    };

會被序列成:

../../v8/src/runtime/http://runtime-literals.cc 72 constant_properties:
0xdf9ed2aed19: [FixedArray]
– length: 6
[0]: 0x1b5ec69833d1 [1]: 0xdf9ed2aec51 [2]: 0xdf9ed2aec71 [3]: 18
[4]: 0xdf9ed2aec91 [5]: 0xdf9ed2aecb1

它是一個FixedArray,FixedArray是V8實現的一個相似於數組的類,它表示一段連續的內存。

那麼,這個連續內存,又如何還原成 JSON 結構對象呢? 

FixedArray主要用於表示數據的存儲位置,在它上面還有一個Map,這個Map用於表示數據的結構。這裏的Map並非哈希的意思,更接近於地圖的意義,用來操做FixedArray表示的這段內存,而且能夠經過index用descriptors迅速地取出key-value

for (int index = 0; index get(index + 0));
  Handle value(constant_properties->get(index + 1));
  Handle name = Handle::cast(key);
  JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE);
}

 

 

 

// Most object types in the V8 JavaScript are described in this file.
//
// Inheritance hierarchy:
// - Object
//   - Smi          (immediate small integer)
//   - HeapObject   (superclass for everything allocated in the heap)
//     - JSReceiver  (suitable for property access)
//       - JSObject
//         - JSArray
//         - JSArrayBuffer
//         - JSArrayBufferView
//           - JSTypedArray
//           - JSDataView
//         - JSBoundFunction
//         - JSCollection
//           - JSSet
//           - JSMap
//         - JSStringIterator
//         - JSSetIterator
//         - JSMapIterator
//         - JSWeakCollection
//           - JSWeakMap
//           - JSWeakSet
//         - JSRegExp
//         - JSFunction
//         - JSGeneratorObject
//         - JSGlobalObject
//         - JSGlobalProxy
//         - JSValue
//           - JSDate
//         - JSMessageObject
//         - JSModuleNamespace
//         - JSV8BreakIterator     // If V8_INTL_SUPPORT enabled.
//         - JSCollator            // If V8_INTL_SUPPORT enabled.
//         - JSDateTimeFormat      // If V8_INTL_SUPPORT enabled.
//         - JSListFormat          // If V8_INTL_SUPPORT enabled.
//         - JSLocale              // If V8_INTL_SUPPORT enabled.
//         - JSNumberFormat        // If V8_INTL_SUPPORT enabled.
//         - JSPluralRules         // If V8_INTL_SUPPORT enabled.
//         - JSRelativeTimeFormat  // If V8_INTL_SUPPORT enabled.
//         - JSSegmentIterator     // If V8_INTL_SUPPORT enabled.
//         - JSSegmenter           // If V8_INTL_SUPPORT enabled.
//         - WasmExceptionObject
//         - WasmGlobalObject
//         - WasmInstanceObject
//         - WasmMemoryObject
//         - WasmModuleObject
//         - WasmTableObject
//       - JSProxy
//     - FixedArrayBase
//       - ByteArray
//       - BytecodeArray
//       - FixedArray
//         - FrameArray
//         - HashTable
//           - Dictionary
//           - StringTable
//           - StringSet
//           - CompilationCacheTable
//           - MapCache
//         - OrderedHashTable
//           - OrderedHashSet
//           - OrderedHashMap
//         - FeedbackMetadata
//         - TemplateList
//         - TransitionArray
//         - ScopeInfo
//         - ModuleInfo
//         - ScriptContextTable
//         - ClosureFeedbackCellArray
//       - FixedDoubleArray
//     - Name
//       - String
//         - SeqString
//           - SeqOneByteString
//           - SeqTwoByteString
//         - SlicedString
//         - ConsString
//         - ThinString
//         - ExternalString
//           - ExternalOneByteString
//           - ExternalTwoByteString
//         - InternalizedString
//           - SeqInternalizedString
//             - SeqOneByteInternalizedString
//             - SeqTwoByteInternalizedString
//           - ConsInternalizedString
//           - ExternalInternalizedString
//             - ExternalOneByteInternalizedString
//             - ExternalTwoByteInternalizedString
//       - Symbol
//     - Context
//       - NativeContext
//     - HeapNumber
//     - BigInt
//     - Cell
//     - DescriptorArray
//     - PropertyCell
//     - PropertyArray
//     - Code
//     - AbstractCode, a wrapper around Code or BytecodeArray
//     - Map
//     - Oddball
//     - Foreign
//     - SmallOrderedHashTable
//       - SmallOrderedHashMap
//       - SmallOrderedHashSet
//     - SharedFunctionInfo
//     - Struct
//       - AccessorInfo
//       - AsmWasmData
//       - PromiseReaction
//       - PromiseCapability
//       - AccessorPair
//       - AccessCheckInfo
//       - InterceptorInfo
//       - CallHandlerInfo
//       - EnumCache
//       - TemplateInfo
//         - FunctionTemplateInfo
//         - ObjectTemplateInfo
//       - Script
//       - DebugInfo
//       - BreakPoint
//       - BreakPointInfo
//       - StackFrameInfo
//       - StackTraceFrame
//       - SourcePositionTableWithFrameCache
//       - CodeCache
//       - PrototypeInfo
//       - Microtask
//         - CallbackTask
//         - CallableTask
//         - PromiseReactionJobTask
//           - PromiseFulfillReactionJobTask
//           - PromiseRejectReactionJobTask
//         - PromiseResolveThenableJobTask
//       - Module
//       - ModuleInfoEntry
//     - FeedbackCell
//     - FeedbackVector
//     - PreparseData
//     - UncompiledData
//       - UncompiledDataWithoutPreparseData
//       - UncompiledDataWithPreparseData
//
// Formats of Object::ptr_:
//  Smi:        [31 bit signed int] 0
//  HeapObject: [32 bit direct pointer] (4 byte aligned) | 01

每一個 heap object 都有個 map 來記錄相關信息。

// All heap objects have a Map that describes their structure.
//  A Map contains information about:
//  - Size information about the object
//  - How to iterate over an object (for garbage collection)
//
// Map layout:
// +---------------+---------------------------------------------+
// |   _ Type _    | _ Description _                             |
// +---------------+---------------------------------------------+
// | TaggedPointer | map - Always a pointer to the MetaMap root  |
// +---------------+---------------------------------------------+
// | Int           | The first int field                         |
//  `---+----------+---------------------------------------------+
//      | Byte     | [instance_size]                             |
//      +----------+---------------------------------------------+
//      | Byte     | If Map for a primitive type:                |
//      |          |   native context index for constructor fn   |
//      |          | If Map for an Object type:                  |
//      |          |   inobject properties start offset in words |
//      +----------+---------------------------------------------+
//      | Byte     | [used_or_unused_instance_size_in_words]     |
//      |          | For JSObject in fast mode this byte encodes |
//      |          | the size of the object that includes only   |
//      |          | the used property fields or the slack size  |
//      |          | in properties backing store.                |
//      +----------+---------------------------------------------+
//      | Byte     | [visitor_id]                                |
// +----+----------+---------------------------------------------+
// | Int           | The second int field                        |
//  `---+----------+---------------------------------------------+
//      | Short    | [instance_type]                             |
//      +----------+---------------------------------------------+
//      | Byte     | [bit_field]                                 |
//      |          |   - has_non_instance_prototype (bit 0)      |
//      |          |   - is_callable (bit 1)                     |
//      |          |   - has_named_interceptor (bit 2)           |
//      |          |   - has_indexed_interceptor (bit 3)         |
//      |          |   - is_undetectable (bit 4)                 |
//      |          |   - is_access_check_needed (bit 5)          |
//      |          |   - is_constructor (bit 6)                  |
//      |          |   - has_prototype_slot (bit 7)              |
//      +----------+---------------------------------------------+
//      | Byte     | [bit_field2]                                |
//      |          |   - is_extensible (bit 0)                   |
//      |          |   - is_prototype_map (bit 1)                |
//      |          |   - is_in_retained_map_list (bit 2)         |
//      |          |   - elements_kind (bits 3..7)               |
// +----+----------+---------------------------------------------+
// | Int           | [bit_field3]                                |
// |               |   - enum_length (bit 0..9)                  |
// |               |   - number_of_own_descriptors (bit 10..19)  |
// |               |   - is_dictionary_map (bit 20)              |
// |               |   - owns_descriptors (bit 21)               |
// |               |   - has_hidden_prototype (bit 22)           |
// |               |   - is_deprecated (bit 23)                  |
// |               |   - is_unstable (bit 24)                    |
// |               |   - is_migration_target (bit 25)            |
// |               |   - is_immutable_proto (bit 26)             |
// |               |   - new_target_is_base (bit 27)             |
// |               |   - may_have_interesting_symbols (bit 28)   |
// |               |   - construction_counter (bit 29..31)       |
// |               |                                             |
// +*************************************************************+
// | Int           | On systems with 64bit pointer types, there  |
// |               | is an unused 32bits after bit_field3        |
// +*************************************************************+
// | TaggedPointer | [prototype]                                 |
// +---------------+---------------------------------------------+
// | TaggedPointer | [constructor_or_backpointer]                |
// +---------------+---------------------------------------------+
// | TaggedPointer | If Map is a prototype map:                  |
// |               |   [prototype_info]                          |
// |               | Else:                                       |
// |               |   [raw_transitions]                         |
// +---------------+---------------------------------------------+
// | TaggedPointer | [instance_descriptors]                      |
// +*************************************************************+
// ! TaggedPointer ! [layout_descriptors]                        !
// !               ! Field is only present if compile-time flag  !
// !               ! FLAG_unbox_double_fields is enabled         !
// !               ! (basically on 64 bit architectures)         !
// +*************************************************************+
// | TaggedPointer | [dependent_code]                            |
// +---------------+---------------------------------------------+

 

 

文有不妥以前,請源站留言告知,本人將及時修正,拜謝

參考文章:

基本數據結構形象解釋 https://blog.csdn.net/qq_23864697/article/details/79727950 

數據結構與算法 - 圖的鄰接表 (思想以及實現方式)www.cnblogs.com/cmusketeer/p/10331450.html

誰說前端就不須要學習數據結構了?來咱們淺談一下js的數據結構 https://www.jianshu.com/p/5e0e8d183102 

JavaScript: new關鍵字建立對象底層原理 https://www.jianshu.com/p/265144a810b7

數據結構和算法 http://www.javashuo.com/article/p-ybnyznxc-e.html

相關文章
相關標籤/搜索