JavaScript数组是如何实现的?

JavaScript数组是如何实现的?,javascript,arrays,associative-array,Javascript,Arrays,Associative Array,也就是说,下面的代码是如何实现的: var sup = new Array(5); sup[0] = 'z3ero'; sup[1] = 'o3ne'; sup[4] = 'f3our'; document.write(sup.length + "<br />"); 在非数组对象上,其行为类似于dict/关联数组。当我在数组对象上执行此操作时,它具有特殊的意义。JavaScript中的什么机制允许这种情况发生?JavaScript是否有某种类型的属性系统可以翻译

也就是说,下面的代码是如何实现的:

var sup = new Array(5);
sup[0] = 'z3ero';
sup[1] = 'o3ne';
sup[4] = 'f3our';
document.write(sup.length + "<br />");
在非数组对象上,其行为类似于dict/关联数组。当我在数组对象上执行此操作时,它具有特殊的意义。JavaScript中的什么机制允许这种情况发生?JavaScript是否有某种类型的属性系统可以翻译

a.length
a['length']
进入“获取”方法和

a.length = 4
a['length'] = 5

进入“设置”方法?

重要的是要知道,当你做
sup['look']=4
您没有使用关联数组,而是修改对象的属性
sup


相当于
sup.look=4sup['length']
将在第一个示例中为实例输出5。

JavaScript中的所有内容都是对象。对于
数组
length
属性返回数组索引项的内部存储区域大小。有些混淆可能是因为
[]
运算符同时适用于数字和字符串参数。对于数组,如果将其与数字索引一起使用,它将返回/设置预期的索引项。如果将其与字符串一起使用,它将返回/设置数组对象的命名属性-除非字符串对应于数值,否则它将返回索引项。这是因为在JavaScript中,通过隐式调用
toString()
将数组索引强制为字符串。坦白地说,这只是让你挠头说“JavaScript,这,这就是他们嘲笑你的原因”的又一个原因

浏览器之间的实际底层表示可能不同(也可能不同)。在使用它时,除了提供的接口之外,我不会依赖其他任何东西


您可以找到有关JavaScript数组的更多信息。

对象继承了调用方
构造函数
名称
属性。

要添加到:在ECMA-262(我相信是3.0规范)中,数组被简单地定义为具有设置属性的行为(参见15.4.5.1)。它没有通用的机制(至少到目前为止)-这只是它的定义方式,以及JavaScript解释器的行为方式。

这实际上取决于您打算如何使用它

[]长度是“神奇的”。
它实际上并不返回数组中的项数。它返回数组中最大的未安装索引

var testArr = [];  testArr[5000] = "something";  testArr.length; // 5000
但是setter背后的方法隐藏在引擎本身中。
某些浏览器中的某些引擎将允许您访问这些神奇方法的实现。 其他人则会将一切完全锁定

因此,不要依赖defineGetter和defineSetter方法,甚至是
\uuu proto\uuu
方法,除非你知道哪些浏览器是你的目标,哪些不是

这将在将来发生变化,在ECMAScript Next/6中编写的选择加入应用程序将可以访问更多


ECMAScript 5兼容的浏览器已经开始在对象中提供
get
set
魔术方法,还有更多。。。但是,要想放弃对旧版和一吨多智能手机的支持,还有一段时间,等等……

JavaScript数组是一个对象,就像任何其他对象一样,但JavaScript赋予它特殊的语法

arr[5] = "yo"
以上是语法糖

arr.insert(5,"yo")
这就是如何向常规对象添加内容。是insert方法内部的内容更改了arr.length的值


在这里查看我的customArray类型实现:

正如其他人所提到的,JavaScript中的属性基本上可以充当数组(或字符串或其他输入)的getter和setter

事实上,你可以自己试试:

const test = [1, 2, 3, 4, 5]
test.length = 3
console.log(test) // [1, 2, 3]
test.length = 5
console.log(test) // Guess what happens here!
据我所知,JavaScript中的数组并不完全像关联数组那样工作,并且根据您正在考虑的JavaScript引擎,您可以将元素放入内存中(假设您可以有混合对象的数组)

顺便说一句,我有点困惑,投票最多的答案一直在传播“一切都是JavaScript中的对象”这一过于简化的神话(或半真半假),否则,您将永远不会学习原语,例如

尝试这样做:

const pippi = "pippi"
pippi.cat = "cat"
console.log(pippi.cat) // Will it work? Throw an error? Guess why again

扰流板:字符串被包装在第二行的特定操作的一次性对象中,然后在下面的一行中,您只需访问原语的一个属性,该属性不存在(前提是您没有使用
string.prototype
或类似工具),因此,您可以获得JavaScript数组的
未定义的

特征

  • 动态-JavaScript中的数组可以动态增长
  • 可以是稀疏的-例如,数组[50000]=2
  • 可以是密集的-例如,数组=[1,2,3,4,5]
  • 在JavaScript中,运行时很难知道数组是密集的还是稀疏的。所以它所能做的就是猜测。所有实现都使用启发式方法来确定数组是密集的还是稀疏的

    例如,上面第2点中的代码可以向JavaScript运行时指示这可能是稀疏数组实现。如果使用初始计数初始化数组,这可能表明这可能是一个密集数组

    当运行时检测到数组是稀疏的时,它将以类似于对象的方式实现。因此,不再维护连续数组,而是构建一个键/值映射


    有关更多参考资料,请参见

    @some:i对javascript不熟悉。我可以在python中实现这种行为,我知道如何重载getitem等,但我不知道javascript的内部是如何工作的。你似乎很熟悉,如果你认为这是微不足道的-请张贴一个答复!我很难理解你的问题。你到底想做什么?你在Javascript中缺少了什么?@Eran:在很多方面
    const pippi = "pippi"
    pippi.cat = "cat"
    console.log(pippi.cat) // Will it work? Throw an error? Guess why again