【问题标题】:Weird Array Objects - JavaScript奇怪的数组对象 - JavaScript
【发布时间】:2018-08-28 03:36:28
【问题描述】:

与其他编程语言相比,JavaScript 中的数组是相当不错的东西,而且它并非没有它的全部怪癖。

包括这个:

// Making a normal array.
var normalArray = [];
normalArray.length = 0;

normalArray.push(1);
normalArray[1] = 2;

normalArray; // returns [1, 2]
normalArray.length // returns 2

是的,以上就是我们都知道的如何制作数组并用元素填充它们,对吧? (暂时忽略normalArray.length = 0 部分)

但是为什么当相同的序列被应用到一个不是纯粹数组的对象上时,它看起来有点不同,并且它的length 属性有点偏离?

// Making an object that inherits from the array prototype (i.e.: custom array)
var customArray = new (function MyArray() {
    this.__proto__ = Object.create(Array.prototype);
    return this
});
customArray.length = 0;

customArray.push(1);
customArray[1] = 2;

customArray; // returns [1, 1: 2]
customArray.length // returns 1

不完全确定这里发生了什么,但我们将不胜感激。

【问题讨论】:

  • 谢谢,但来自链接“stackoverflow.com/questions/34801251/…”的问题并不完全相关。它询问自定义对象对 Array 原型的继承;这不是为什么向自定义数组和普通数组添加元素(以不同方式)似乎有点狡猾的问题。
  • "直到并包括 ES5,无法以通常的构造函数原型方式干净地扩展 Array而不会丢失功能,相反,您必须向 Array 实例添加属性” 自定义数组将是 Array 的扩展,不是吗?
  • 嗯,你说得有道理。是的,自定义数组基本上是Array 的扩展。这是否真的表明没有办法使数组的这种奇怪行为无效..?你引用了一些东西,我可以看看你从哪里得到的参考吗?
  • 我链接的问题的公认答案;)。您可以通过使用您最喜欢的搜索引擎查找子类或扩展 javascript 数组来找到类似的报告

标签: javascript


【解决方案1】:

这可能不是完美的答案,但根据我对 Javascript 数组的理解,它们与通常的对象有点不同。 (主要是因为它维护了一个长度属性,而对象没有)。

因此,如果我们以您的代码为例:

var normalArray = [];

这是在 Javascript 中创建数组的正确方法。但是下面的呢?

var customArray = new (function MyArray() {
    this.__proto__ = Object.create(Array.prototype);
    return this
});

它们是一样的吗?让我们看看..

Array.isArray(normalArray); // true -> [object Array]
Array.isArray(customArray); // false -> [object Object]

所以很明显,虽然你继承自数组原型,但它并没有真正创建Array 类型的对象。它只是创建一个普通的 JS 对象,但具有继承的数组函数。这就是当您使用customArray.push(1); 设置值时它会更新长度的原因。

但是由于您的customArray 只是一个常规对象,而对于常规JS 对象,[] 表示法用于设置属性,它不会更新长度(因为Objects 没有@ 987654329@财产)

希望清楚:)

【讨论】:

    【解决方案2】:

    您尝试创建的数组不是纯数组(您可能知道)。它基本上是一个 JavaScript 对象,应该表现得像一个对象。

    在将对象视为数组时,由您来维护它的所有类似数组的特性。

    您必须特别为它分配一个length 属性,并且您做得正确。

    接下来,Array.prototype 中的 push 方法应该向数组中插入一个元素并递增 length 属性(如果有),所以它确实将 0 递增到 1。你去吧,@987654325 @ 现在是 1。

    接下来,您使用属性赋值的文字符号Object,类似于customArray['someProperty'] = 1

    虽然使用文字表示法,但不会调用来自 Array.Prototype 的任何方法,因此 customArray 对象永远不知道它必须像数组一样工作,并且其长度属性不受影响。它只是表现得像一个对象,你得到你所得到的。

    请记住,length 只是 Array 类上的一个属性,并且该属性会被 Array 上的每个方法适当地递增和递减。

    注意:不建议使用类似数组的对象,并且完全由您来维护此类对象的索引和其他数组内容。

    【讨论】:

      【解决方案3】:

      据我所知,你的功能有问题:

      return this
      

      这应该是

      return (this);
      

      只需修复您可能遇到的任何潜在错误。另一件事是您没有使用var 关键字来声明customArray。这些错误可能会破坏您的代码。

      【讨论】:

      • 首先,感谢您注意到我没有正确初始化数组对象;其次,我尝试了(this) 并没有改变任何东西;第三,我对这里发生的事情比解决问题更感兴趣。在我尝试解决它之前,我需要知道导致这种行为的问题是什么。不过感谢您的回答,非常受欢迎。
      • 我只是指出可能对您的代码有影响的语法错误
      • @JBDouble05 我不知道在this 周围使用括号() 会有所不同。您能否指出一些关于 JS 语法变化的参考/解释?我没有找到任何相关信息。
      • 抱歉,这样做的语法很好。它可能只是您使用的严格浏览器。
      • 我同意使用分号 ; 确实是很好的语法,因为它避免了一些细微的潜在错误,但括号部分对我来说似乎有点过分了,我不会评价“良好的语法”。谢谢你的澄清。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 2023-03-17
      相关资源
      最近更新 更多