如何实现javascript数组?

时间:2008-12-14 00:11:49

标签: javascript arrays associative-array

即,以下代码如何:

var sup = new Array(5);
sup[0] = 'z3ero';
sup[1] = 'o3ne';
sup[4] = 'f3our';
document.write(sup.length + "<br />");

输出'5'作为长度,当你所做的就是设置各种元素?

我对此代码的“问题”是,如果不调用lengthgetLength()方法,我无法理解setLength()的更改方式。当我执行以下任何操作时:

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

在非数组对象上,它的行为类似于dict / associative数组。当我在数组对象上执行此操作时,它具有特殊含义。 JavaScript中的哪种机制允许这种情况发生? javascript是否有某种类型的属性系统翻译

a.length
a['length']

进入“get”方法和

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

进入“设定”方法?

9 个答案:

答案 0 :(得分:13)

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

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

您可以在MDN找到有关Javascript数组的更多信息。

答案 1 :(得分:2)

这实际上取决于你打算用它做什么。

[].length是“神奇的” 它实际上并不返回数组中的项数。它返回数组中最大的instated索引。

var testArr = [];  testArr[5000] = "something";  testArr.length; // 5000

但是设定者背后的方法隐藏在引擎本身中 某些浏览器中的某些引擎会让您访问这些魔术方法的实现。 其他人会把一切都完全锁定。

所以不要依赖defineGetter和defineSetter方法,甚至是真的__proto__方法,除非你知道哪些浏览器是你知道的目标,哪些不是你。

将来会有所改变,用ECMAScript Next / 6编写的选择加入应用程序可以访问更多。

符合ECMAScript 5标准的浏览器已经开始在对象中提供getset魔法方法了,还有更多内容......但是在转发支持之前可能还需要一段时间对于oldIE和一吨智能手机等等......

答案 2 :(得分:2)

添加到tvanfosson的答案:在ECMA-262(3.0规范,我相信)中,数组被简单地定义为具有设置属性的这种行为(见15.4.5.1)。它没有一般的机制(至少截至目前) - 这就是它的定义方式,以及javascript解释器必须如何表现。

答案 3 :(得分:2)

重要的是要知道当你执行sup['look'] = 4;时,你没有使用关联数组,而是修改对象sup的属性。它等同于sup.look = 4;,因为您可以随时在javascript对象上动态添加属性。 sup['length']将在第一个示例中输出实例输出5。

答案 4 :(得分:1)

如果您打算实现具有类似阵列访问权限的对象,Array Mozilla dev center article是一个很好的资源。不幸的是,我不知道Array实现的深入细节,但该文章中有很多细节。

答案 5 :(得分:1)

Array对象继承length中的callerconstructorFunction.prototypename属性。

答案 6 :(得分:0)

JavaScript数组的特征

  1. 动态-Javascript中的数组可以动态增长.push
  2. 可以稀疏-例如array [50000] = 2;
  3. 可以密集-例如数组= [1、2、3、4、5]

在Javascript中,运行时很难知道数组是密集的还是稀疏的。因此,所有可以做的就是猜测。所有实现都使用启发式方法来确定数组是密集的还是稀疏的。例如,上面第2点中的代码可以向javascript运行时指示这很可能是稀疏数组的实现。如果使用初始计数初始化阵列,则可能表明这可能是密集阵列。

当运行时检测到数组为稀疏数组时,它的实现方式与对象相似。因此,建立了键/值映射而不是维护连续的数组。

更多参考- https://www.quora.com/How-are-javascript-arrays-implemented-internally

答案 7 :(得分:0)

正如其他人提到的那样,JavaScript中的属性基本上可以充当数组(或字符串或其他输入)的获取器和设置器。

事实上,您可以自己尝试:

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!

据我所知,JS中的数组不能完全像关联数组那样工作,并且有一些元素放置在内存as contiguously as possible中(假设您可以有混合对象的数组),具体取决于JS引擎您正在考虑。

作为一个旁注,我最困惑的是,投票最多的答案一直散布着“一切都成为JavaScript对象”的过于简单的神话(或半真相)。 that is not exactly true,否则,例如,您将永远不会学习基元。

尝试执行以下操作:

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

Spoiler:将字符串包装在第二行中用于该特定操作的一次性对象中,然后在下面的示例中,您将访问不存在的原语的属性(前提是您没有使用{ {1}}等),则得到String.prototype

答案 8 :(得分:0)

JavaScript数组就像任何其他对象一样是一个对象,但JavaScript为它提供了特殊的语法。

arr[5] = "yo"

以上是句法糖
arr.insert(5,"yo")

这是你如何将东西添加到常规对象。它是 insert 方法中改变arr.length

值的内容

在此处查看我对customArray类型的实现:http://jsfiddle.net/vfm3vkxy/4/