若是有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出来的)。其实,说存储于堆中,也不太准确,由于,引用类型的数据的地址指针是存储于栈中的,当咱们想要访问引用类型的值的时候,须要先从栈中得到对象的地址指针,而后,在经过地址指针找到堆中的所须要的数据。这个后讲,首先咱们要搞清楚
数据在内存中的存储结构,也就是物理结构,分为两种:顺序存储结构和链式存储结构。
顺序存储结构:是把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。数组就是顺序存储结构的典型表明。
链式存储结构:是把数据元素存放在内存中的任意存储单元里,也就是能够把数据存放在内存的各个位置。这些数据在内存中的地址能够是连续的,也能够是不连续的。链表就是顺序存储结构的典型表明。
和顺序存储结构不一样的是,链式存储结构的数据元素之间是经过指针来链接的,咱们能够通使用指针来找到某个数据元素的位置,而后对这个数据元素进行一些操做。
数组和队列均可以实现栈和链表。
打个比方说一下顺序存储结构和链式存储结构的区别:
好比去银行取钱,顺序存储结构就至关于,全部的客户按照先来后到的顺序有序的的坐在大厅的椅子上(注意:是有顺序的坐着哦)。
而链式存储结构至关于,全部的客户只要一到银行,大堂经理就给他们每人一个号码,而后他们能够随便坐在哪一个椅子上(随便坐,不须要按照什么顺序坐),只须要等待工做人员广播叫号便可。
而每一个客户手里的号码就至关于指针,当前的指针指向下一个存储空间,这样,全部不连续的空间就能够被有顺序的按照线性链接在一块儿了。
各类语言在处理堆栈的原理上都大同小异。
堆是动态分配内存,内存大小不一,也不会自动释放
栈是自动分配相对固定大小的内存空间,并由系统自动释放。栈先进后出(LIFO,last in first out),队列后进先出(FIFO,first in first out)。
数组数据结构是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)能够计算出该元素对应的存储地址。数组寻址容易,插入和删除困难的问题,而链表增删容易,查找困难。栈能够用数组或链表实现(c艹、java等基本功)。
集合表示一组互不相同的元素(不重复的元素)。
字典存储的是[键,值]对,其中键名是用来查询特定元素的。
经典的数据结构大概就那么几种,list、stack、queue、linkedList、dictionary、hash、set、tree、graph......
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的实现》
在建立一个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://www.zhoulujun.cn/html/webfront/ECMAScript/js/2016_0219_7607.html
文有不妥以前,请源站留言告知,本人将及时修正,拜谢
参考文章:
基本数据结构形象解释 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