有没有什么办法把现有的Javascript对象到一个数组而无需创建一个新的独立的阵列?

问题描述 投票:9回答:3

有很多的提到上differentes读数阵列在Javascript中一类特殊的对象。例如在这里:

https://www.codingame.com/playgrounds/6181/javascript-arrays---tips-tricks-and-examples

这样,由于一个object是性质(或键)和值的集合,想到如果有开始与一个对象方式,并与一个阵列Array.isArray()返回true该对象的方法模拟结束(在这个意义上数组)。我已经开始看阵列特性:

let arr = [0, 1, 2, 3, 4, 5];
console.log(Object.getOwnPropertyNames(arr));
console.log(Array.isArray(arr));

所以,我想使用一个对象来模拟相同的:

let arrEmulation = {0:0, 1:1, 2:2, 3:3, 4:4, 5:5, "length":6};
console.log(Object.getOwnPropertyNames(arrEmulation));
console.log(Array.isArray(arrEmulation));

Array.isArray(arrEmulation)仍然返回false。首先,我要道歉,如果这是一个愚蠢的问题,但有什么办法可以手动转换的objectarray加入特殊性能(或钥匙)呢?

请注意,我不想知道如何对象转换为数组,我只是想了解哪些是那些特别的东西,使可能的解释就像一个数组的对象。

javascript arrays object
3个回答
6
投票

我不认为这是可能的,严格意义上,给出的标准规范。仰望Array.isArray

如果[[类]]内部arg的属性的值是“阵列”,则返回真。

因此,对于Array.isArray(arrEmulation)返回true,你必须以某种方式修改对象的[[Class]]Array,而不是Object。但是,看着ES5的关于8.6.2 Object Internal Properties and Methods [[Class]]

注意:该规范没有定义的ECMAScript语言操作符或内置函数允许一个程序来修改一个对象的[[类]]或[[原型]]内部特性或的[[扩展]]的值从假变为真。该修改的实施特定扩展[[类]],[[原型]]或[[扩展]]不得违反在前面的段落中定义的变量。

也:

请注意,这个规范没有提供任何手段的程序访问除了通过Object.prototype.toString该值

所以,官方的规范没有提供一种方式来做到这一点在ES5 - 如果有办法做到这一点,那将是非标准和实现有关。

这就是说,除非你绝对需要使用Array.isArray或有Object.prototype.toString.call(arrEmulation)返回[object Array],你仍然可以使用Object.setPrototypeOf设置arrEmulation的原型Array.prototype,让您在对象上使用阵列的方法和具有instanceof Array返回true

const arrEmulation = {0:0, 1:1, 2:2, "length":6};
Object.setPrototypeOf(arrEmulation, Array.prototype);

console.log(arrEmulation instanceof Array);
arrEmulation.forEach((value) => {
  console.log(value);
});
// Internal [[Class]] property is still `Object`, though:
console.log(Object.prototype.toString.call(arrEmulation));
// Unlike a true array:
console.log(Object.prototype.toString.call([]));

console.log('-----');

// although you can set the `toStringTag` to the string 'Array' in ES6+,
// it is cosmetic only and does not pass an `Array.isArray` test:
arrEmulation[Symbol.toStringTag] = 'Array';
console.log(Object.prototype.toString.call(arrEmulation));
console.log(Array.isArray(arrEmulation));

但请注意,你应该avoid在实际代码中使用Object.setPrototypeOf

警告:更改对象的[[Prototype]],通过现代的JavaScript引擎如何优化属性访问,一个非常缓慢的操作,在每一个浏览器和JavaScript引擎的性质。对改变遗传性能的影响是细微的,遥远的,并不仅限于简单的Object.setPrototypeOf(...)声明中所花费的时间,而且可以延伸到能够访问其[[Prototype]]已经改变任何对象的任何代码。如果你关心性能,你应该避免设置对象的[[Prototype]]。相反,使用[[Prototype]]创建具有所需Object.create()一个新的对象。

(当然,Object.create包括创建新的对象,这是你想做的事,这是改变现有的arrEmulation对象不同的是什么)

虽然目前没有看起来是一个办法做到这一点在ES6 +或者 - 其文本有几分相似,但不完全相同。具体而言,Array.isArray返回true,所讨论的对象needs to be“阵列异国对象”(或指向一个Proxy) - 但setPrototypeOf只设置原型,既不它也没有任何其他方法可以使对象实际上成为数组异域对象(它看起来像它必须由解释器本身构造,并且不足够emulatable)。


2
投票

JavaScript是所有关于原型继承:

Prototype Inheritance所有JavaScript对象继承原型属性和方法:

Date对象从Date.prototype继承Array对象继承Array.prototype Person对象继承的Person.prototype的是的Object.prototype的原型继承链的顶端。

Date对象,Array对象和Person对象从Object.prototype中继承。

正如在这里看到IsArray的是在该阵列对象的原型链的功能。

如在MDN Array.isArray()备用建议如果IsArray的不存在的填充工具是:

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

因此,类型由原型链,而不是返回什么价值确定。

同样,按照氧化钛捷思锐的回答

const newArray = Array.from(arrEmulation) // [0, 1, 2, 3, 4, 5]
Array.isArray(newArray)

什么它确实是来自于原型只是改变对象到一个数组中。

更深经历IsArray的感谢@Kaiido让我深入挖掘。阵列是阵列检查these there points

如果Type(ARG)不是Object,返回false。如果[[类]]内部arg的属性的值是“阵列”,则返回真。返回FALSE。

And

阵列实例继承来自阵列原型对象的属性和它们的[[类]]内部属性值为“阵列”。 Array实例还具有以下属性。


0
投票

您可以将任何通过使用Array.from足够接近到一个数组()。在您的例子中,我们可以只要致电:

const arrEmulation = {0:0, 1:1, 2:2, 3:3, 4:4, 5:5, length: 6};

const newArray = Array.from(arrEmulation) // [0, 1, 2, 3, 4, 5]
Array.isArray(newArray) // true
© www.soinside.com 2019 - 2024. All rights reserved.