我知道在python中我可以使用列表来快速排序和字典,以便更快地搜索事物(因为可以对不可变对象进行哈希处理)。对于javascript也一样吗?经过多次搜索后,我还没有看到关于javascript中数据类型性能的任何信息。
答案 0 :(得分:0)
是。 “Javascript中的对象与数组是Python的字典与列表”。 性能优劣也是一样的。如果数字索引适合于任务,则列表更有效,并且字典对于必须由字符串访问的长列表更有效。
var dict = {};
dict['apple'] = "a sweet edible fruit";
dict['boy'] = "a young male human";
var list = [];
list.push("apples");
list.push("oranges");
list.push("pears");
答案 1 :(得分:0)
我一直在寻找可以回答这个问题的书目和其他资料。我知道这不是最佳答案,但让我尝试一个涉及一些概念的答案,以便我们讨论此主题。
尽管它可能暗示javascript中的数组和对象就像列表和字典,但它们是不同的,因为每种语言以不同的方式编写,具有不同的基本哲学,概念和目的。
就Java语言而言,似乎Arryas和Objects更像是哈希表。与直觉相反,数组只是javascript的另一种内置对象。实际上,正如他们在ECMAScript Specification 6.1.7
中所说的那样对象类型
从逻辑上讲,对象是属性的集合。每个属性是 数据属性或访问器属性:
数据属性将键值与ECMAScript语言相关联 值和一组布尔属性。访问者属性关联 具有一个或两个访问器函数的键值,以及一组布尔值 属性。访问器函数用于存储或检索 与属性关联的ECMAScript语言值。 使用键值标识属性。属性键值为 ECMAScript字符串值或符号值。所有字符串和 符号值(包括空字符串)可以用作属性键。 属性名称是作为字符串值的属性键。
整数索引是一个字符串值的属性键,它是规范的 数字字符串(请参见7.1.16),其数字值为+0或a 正整数≤253-1。数组索引是其整数索引 数值i的范围为+0≤i <232-1。
属性键用于访问属性及其值。那里 属性的两种访问方式:get和set,对应于 值检索和赋值。属性 通过获取和设置访问权限可访问,包括自己的属性 是对象的直接部分,继承的属性是 由另一个关联的对象通过属性继承提供 关系。继承的属性可以是自己的,也可以是继承的 关联对象的属性。对象的每个属性 必须每个都有一个与 该对象的其他自身属性。
然后about the arrays,它指定:
22.1Array对象
数组对象是特殊对象,它们对某些类的属性名称给予特殊对待。
按照上面的逻辑,以及在规范中所说的那样,该语言被认为是javascript中的所有类型都扩展了一个全局对象,然后添加了新的方法和属性以具有不同的行为。
语言规范和在实际运行时环境中必须如何实现之间存在差距。尽管每种实现都有自己的逻辑,但似乎大多数逻辑都有相似之处。
大多数JavaScript解释器使用类似字典的结构(哈希 基于函数)将对象属性值的位置存储在 记忆。这种结构使得可以检索以下属性的值: JavaScript在计算上比在JavaScript中更昂贵 非动态编程语言,例如Java或C#。在Java中,所有 对象属性由固定的对象布局决定, 编译,并且无法在运行时动态添加或删除 (好吧,C#具有动态类型,这是另一个主题)。结果是, 属性的值(或指向这些属性的指针)可以是 作为固定缓冲区存储在内存中的连续缓冲区 彼此之间。偏移的长度可以很容易地根据 属性类型,而这在JavaScript中是不可能的 属性类型可以在运行时更改。
由于这会使javascript变得毫无效率,工程师不得不采用一些巧妙的解决方法来解决此问题。跟随this other article:
如果您访问属性,例如object.y,JavaScript引擎看起来 在JSObject中输入键“ y”,然后加载相应的属性 属性,最后返回[[Value]]。
但是这些属性属性存储在内存中的什么位置?我们应该吗 将它们存储为JSObject的一部分?如果我们假设我们会看到 以后再有更多具有此形状的对象,那么存储 完整的字典,其中包含属性名称和属性 JSObject本身,因为对所有对象重复属性名称 具有相同的形状。重复很多,不必要地 内存使用情况。作为优化,引擎会存储 单独对象。
此Shape包含所有属性名称和属性,但 为他们的[[Value]]。而是Shape包含了 JSObject内部的值,以便JavaScript引擎知道 在哪里找到值。每个具有相同形状的JSObject都指向 精确到此Shape实例。现在每个JSObject只需要存储 该对象唯一的值。
当我们有多个对象时,好处显而易见。不管怎样 有很多物体,只要它们具有相同的形状,我们就 必须一次存储形状和属性信息!
所有JavaScript引擎都使用形状作为优化,但它们没有 都称它们为形状:
- 学术论文称它们为“隐藏类”(令人困惑的JavaScript类)
- V8称它们为Maps(令人困惑的JavaScript Maps)
- Chakra称它们为Types(混淆了JavaScript的动态类型和typeof)
- JavaScriptCore称它们为结构 * SpiderMonkey称它们为Shapes
Python使用不同的方法来实现列表,列表似乎更像是一些动态数组,而不是在C中可以找到的实际数组,但是它们始终专注于节省时间和复杂性。运行。 As this FAQ cited form the PyDocs says:
Python的列表对象实际上是变长数组,而不是 Lisp样式的链表。该实现使用一个连续数组 引用其他对象,并保持指向该数组和 列表头结构中数组的长度。
这使索引列表(L [i])的操作成本为 与列表的大小或索引的值无关。
在添加或插入项目时,引用数组为 调整大小。运用一些技巧来提高性能 重复添加项目;当数组必须增长时,一些额外的 已分配空间,因此接下来的几次不需要实际 调整大小。
像javascript一样,Python的列表也不要求是同质的,因此它们并不是其他“强类型”数据结构的实际实现,这些数据结构只必须包含相同的实体,例如整数,字符串等。
与javascript一样,语言的规范实际实现是两件事。取决于您是否使用Cpython,Jython,IronPython等,在将python解释为机器代码的过程中,内存管理和在后台运行的实际功能将产生不同的作用。
我知道这不是最好的来源,但是as I found discussed in Quora:
与其名称含义相反,Python列表实际上是数组(...)。 具体来说,它们是具有指数的动态数组 过度分配,这使得如下代码具有线性 复杂性:
lst = [] for i in xrange(0, 100000): lst.append(i)
Jython和IronPython之类的替代实现似乎使用了 任何本地动态数组类及其底层语言 (分别是Java和C#)提供的,因此它们具有相同的性能 特性(精确的基础类似乎是ArrayList Jython和IronPython的C#列表)。
(...)数组在技术上存储指针而不是对象 本身,从而允许数组仅包含 具体尺寸。在底层的各处都有指针 实现是动态类型语言的共同特征,并且 实际上,任何试图假装的语言都没有 指针。
如官方文档在其"History and Design FAQ"中所述
CPython的字典被实现为可调整大小的哈希表。 与B树相比,这为查找提供了更好的性能( 在大多数情况下,是迄今为止最常见的操作),并且 实施比较简单。
字典的工作方式是为存储在 使用hash()内置函数的字典。哈希码有所不同 广泛取决于密钥;例如,“ Python”哈希 -539294296,而“ python”(一个相差一个位的字符串)则散列为1142331976。然后使用哈希码来计算 内部数组中将存储值的位置。假设 您存储的键都具有不同的哈希值, 表示字典需要固定的时间–计算机科学中的O(1) 表示法–检索密钥。这也意味着没有排序顺序 键被保留,并以.keys()和 .items()do将以任意方式输出字典的内容 混乱的订单。
关于语言,有两件事:一件事涉及语言的工作方式,语法,语义,逻辑和哲学。另一方面,您可以在特定的运行时,解释器或编译中实际实现该语言。 这样,尽管(理论上)您拥有一个Python或一个Javascript,但是您可以拥有CPython,IronPython Jython等。另一方面,您有SpiderMonkey,V8等。
但是,在谈到每个运行时如何实现数组/列表和对象/字典的语言功能以及它们的相似性时,似乎Javascript选择了基于原型的继承模型,使原型成为一种对象。因此对象和字典都更像是哈希表,而不是实际的数组。 另一方面,Python在数据结构方面具有更多的特色,无论是在其库中还是在解释器如何处理它们方面,都使用数组或动态数组使Pyton's Lists变得栩栩如生,并使用哈希表字典,使它们与javascript中的对象更加相似。