JavaScript - 数组和类数组对象之间的区别

IT技术 javascript arrays
2021-01-17 14:20:10

我在 JavaScript 中经常遇到术语“类数组对象”。它是什么?它和普通数组有什么区别?类数组对象和普通对象有什么区别?

5个回答

它是什么?

一个具有非负Integer长度属性对象通常还有一些索引属性。例如

var ao1 = {length: 0},                     // like []
    ao2 = {0: 'foo', 5: 'bar', length: 6}; // like ["foo", undefined × 4, "bar"]

您可以将阵列状物体,以他们的阵列使用同行Array.prototype.slice

var arr = Array.prototype.slice.call(ao1); // []

它和普通数组有什么区别?

它不是由Array 字面量构造的,Array也不是用Array 字面量 构造的[],因此(通常)不会从Array.prototype. 长度属性通常不会自动更新两种。

ao1 instanceof Array; // false
ao1[0] = 'foo';
ao1.length; // 0, did not update automatically

类数组对象和普通对象有什么区别?

没有区别。即使是正常的数组对象的JavaScript

ao1 instanceof Object; // true
[] instanceof Object; // true
@Paul_S。我认为这更像是该isArray方法的一个陷阱,因为它[[class]]在幕后使用了内部属性,而不是证明一个对象Array.prototype是一个类似数组的对象,而不是一个具有可用数组方法的对象(通过继承自Array.prototype,这也意味着它有一个length属性)并且数字索引不是类似数组的,它是一个数组。
2021-03-23 14:20:10
@Taurus 如果您以 ES5 方式为某些自定义对象设置原型,您将获得 Array-likes Array.isArray(Object.create(Array.prototype)); // false如果你使用 ES6+ class A2 extends Arrayand super,你会得到数组Array.isArray(new A2); // true
2021-03-24 14:20:10
@techie_28 添加一个长度,它会排序,没有长度你的对象不是类似数组的
2021-03-31 14:20:10
@Taurus 在 ES5 版本中,即使你做了一些类似function Foo() {}; Foo.prototype = Object.create(Array.prototype); f = new Foo;考虑f[0] = 1; f.length; // => 0. 这意味着它不是真正的数组,因为设置索引不会对长度产生预期的副作用。用 ES6+ 做同样的事情确实对长度有副作用
2021-04-01 14:20:10
and so (usually) won't inherit from Array.prototype小心详细说明“通常”部分?如果继承自 ,它不是类似数组的东西而是数组Array.prototype吗?
2021-04-09 14:20:10

著名的HTMLCollection( documentation ) 和arguments( documentation ) 是自动创建的类数组对象。

HTMLCollection真实数组示例之间的一些快速数组(例如)差异:

var realArray = ['value1', 'value2'];
var arrayLike = document.forms; 

相似之处:

长度吸气剂是一样的:

arrayLike.length; // returns 2;
realArray.length; // returns 2; //there are 2 forms in the DOM.

索引 getter 是相同的:

arrayLike[0]; // returns an element.
realArray[0]; // returns an element. ('value')

他们都是objects

typeof arrayLike; // returns "object"
typeof realArray; // returns "object"

区别:

在阵列状的join()concat()includes()等等,方法是不是一个功能:

arrayLike.join(", "); // returns Uncaught TypeError: arrayLike.join is not a function (also relevant to `concat()`, `includes()` etc.)
realArray.join(", "); // returns "value1, value2"

数组 like 并不是真正的数组:

Array.isArray(arrayLike); //returns "false"
Array.isArray(realArray); //returns "true"

在像你不能设置长度属性的数组中:

arrayLike.length = 1;
arrayLike.length; //return 2; //there are 2 forms in the DOM.
realArray.length = 1;
realArray.length; //return 1;

我认为,在 ES6 中,如果某些东西是可迭代的(具有[Symbol.iterator]属性),则它类似于 Array

“类数组对象”是存在的事物的实际名称。它定义了可以具体应用于以特定方式构建和使用的对象的属性。
2021-03-24 14:20:10
你认为还是你知道?根据这篇文章dmitripavlutin.com/javascript-array-from-applications 中的声明,您可能是对的 -> 此外,您可以将 Array.from() 与实现可迭代协议的任何对象或原语一起使用
2021-03-24 14:20:10

也有性能差异。在本视频中, Mathias Bynens 建议在类数组对象上使用数组,因为 V8 已针对常见数组进行了优化。

首先,数组是一个专门的对象。专长于:

  • 有一种特殊的文字语法 [ … ]
  • 有一个length属性会自动更新
  • 数组原型包括您通常期望从数组中获得的函数

另一个明显的特征是所有元素都有一个数字索引。

从 JavaScript 的角度来看,任何具有length属性的对象都足够接近,可以被视为类数组对象:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
console.log(arrayLikeObject);

length物业并不一定是正确的。即使在普通数组中,也有可能强制length不是实际元素的数量。缺失的元素全部返回undefined

您可以使用 将类似数组的对象转换为真正的数组Array.from()此函数将采用各种值,但最简单的是:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
var array = Array.from(arrayLikeObject);
console.log(array);

从这里开始,数组具有所有常用的属性和方法。在上面的例子中,属性[1]被复制到新数组中,但元素[name]不是,因为它不属于真正的数组。

Array.from()函数还接受一个映射函数作为第二个参数。这允许您在运输过程中进行任何需要的更改:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
var array = Array.from(arrayLikeObject,
    (element,index) => element?element.toUpperCase():`Item ${index}`
);
console.log(array);