【问题标题】:What is empty inside an array? e.g. [empty X 5]数组中什么是空的?例如[空×5]
【发布时间】:2019-12-12 11:26:08
【问题描述】:

对不起,这里的标题误导了,我无法框出任何合适的标题。

当数组中没有任何东西时,我对数组感到困惑(empty X n 打印)但它们有长度。
例如我通过const a = [,,,] 创建数组。这将创建一个长度为 3 但其中没有任何内容的数组。如果我在浏览器控制台中打印它,它会打印以下内容:

What does empty mean here? 如果我运行 map 或 forEach 函数并尝试控制台某些东西,我什么也得不到。

添加了一些代码。

const a = [,,,]

console.log("print a: ",a)
console.log("print a.length: ",a.length)
console.log("print typeof a[0]: ", typeof a[0])
console.log("a.forEach((data, index) => { console.log(data, index) }): ", a.forEach((data, index) => { console.log(data, index) }))
console.log("")


const b = [undefined, undefined, undefined]

console.log("print b: ", b)
console.log("print b.length: ", b.length)
console.log("print typeof b[0]: ", typeof b[0])
console.log("b.forEach((data, index) => { console.log(data, index) }): ", b.forEach((data, index) => { console.log(data, index) }))
console.log("")

console.log("compare a[0] and b[0]: ", a[0] === b[0])

唯一不同的是当我打印 a 和 b 时(尽管 stackoverflow 控制台打印它们相同,但浏览器控制台打印不同)以及当我尝试循环遍历数组时。还有 momentjs isEqual 给他们相等 (jsfiddle here)

我的主要疑问是:

  • 它是什么类型的数组?
  • 这里的空是什么意思?
  • 它与包含所有未定义值或空数组的数组有何不同?不是吗?
  • 我们是使用它还是使用它的任何示例用例

我已经阅读了关于 null 和 undefined 数组值的内容并理解了它。但是对于这个,我没有找到任何合适的东西。我发现的大部分搜索都与 const a = [] 是空数组或如何检查数组是否为空等有关。

因此,如果有人可以解释或提供任何适当的链接以供阅读,那将非常有帮助。

如果我应该添加其他内容,请告诉我。

【问题讨论】:

  • Empty 就是字面上的意思 - 该插槽中没有数据。不是undefined,也不是null - 数组是稀疏的。
  • @VLAZ,如果我错了,请纠正我。类似于:null 表示内存分配了 null 值(或引用指向 null),undefined 表示分配了内存位置但不存在值(或引用存在但不指向任何地方)但 empty means that memory is not even allotted (or reference doesn't exists at all)?
  • @Sunil 有点像。 在数组中是否分配内存是一个实现细节。 JS 中的数组不一定像其他语言那样被赋予连续的内存,因此稀疏数组肯定可以有空槽甚至不占用空间。 nullundefined 都是,所以它们是存在的。但是,可能所有设置为null 的绑定实际上都指向一个值,因此您不会得到null 的多个“副本”。不确定是否已经完成。 undefined 可能是一个实际值或一个缺少值 - 例如a = {}; a.foo.

标签: javascript arrays


【解决方案1】:

稀疏数组简介

首先澄清一下您创建的内容称为稀疏数组。简单来说,稀疏数组与普通数组类似,但并非所有索引都有数据。在某些情况下,比如 JavaScript,这会导致对它们的处理更加重要。其他语言只是有一个固定长度的普通数组,其中一些值在某种意义上是“零”(取决于什么值可以表示特定数组的“无” - 可能是 0null"",等)。

空槽

稀疏数组中的空槽正是它听起来的样子——没有填充数据的槽。与大多数其他实现不同,JavaScript 数组不是固定大小的,甚至可以有一些索引missing。例如:

const arr = [];   // empty array
arr[0] = "hello"; // index 0 filled
arr[2] = "world"; // index 2 filled

你会得到一个没有索引 1 的数组。它不是null,也不是空的,它不存在。当您拥有一个没有属性的对象时,这与您得到的行为相同:

const person = {foo: "hello"};

您有一个具有属性foo 的对象,但它没有bar 属性等。和之前的数组没有索引1一模一样。

JavaScript 表示“未找到值”的唯一方式是使用 undefined,但是这会混淆

  • "该属性存在且分配给它的值为undefined"
  • “该属性根本不存在”

这里举个例子:

const person1 = { name: "Alice", age: undefined };
const person2 = { name: "Bob" };

console.log("person1.age", person1.age);
console.log("person2.age", person2.age);

console.log("person1.hasOwnProperty('age')", person1.hasOwnProperty('age'));
console.log("person2.hasOwnProperty('age')", person2.hasOwnProperty('age'));

在任何一种情况下尝试解析 age 时都会得到 undefined,但原因不同。

由于 JavaScript 中的数组 对象,因此您会得到相同的行为:

const arr = [];   // empty array
arr[0] = "hello"; // index 0 filled
arr[2] = "world"; // index 2 filled

console.log("arr[1]", arr[1]);

console.log("arr.hasOwnProperty(1)", arr.hasOwnProperty(1));

为什么重要

稀疏数组在 JavaScript 中得到了不同的处理。即,迭代项目集合的数组方法将仅通过 已填充 槽,并会省略空槽。这是一个例子:

const sparseArray = [];   // empty array
sparseArray[0] = "hello"; // index 0 filled
sparseArray[2] = "world"; // index 2 filled

const arr1 = sparseArray.map(word => word.toUpperCase());

console.log(arr1); //["HELLO", empty, "WORLD"]


const denseArray = [];     // empty array
denseArray[0] = "hello";   // index 0 filled
denseArray[1] = undefined; // index 1 filled
denseArray[2] = "world";   // index 2 filled

const arr2 = denseArray.map(word => word.toUpperCase()); //error

console.log(arr2);

如您所见,迭代稀疏数组很好,但如果数组中有显式的undefined,那么word => word.toUpperCase() 将失败,因为wordundefined

如果您想要运行.filter.find.map.forEach 等的数字索引数据,则稀疏数组非常有用。再说明一下:

//some collection of records indexed by ID
const people = [];
people[17] = { id: 17, name: "Alice", job: "accountant" , hasPet: true  };
people[67] = { id: 67, name: "Bob"  , job: "bank teller", hasPet: false };
people[3] =  { id: 3 , name: "Carol", job: "clerk"      , hasPet: false };
people[31] = { id: 31, name: "Dave" , job: "developer"  , hasPet: true  };


/* some code that fetches records */
const userChoice = 31;
console.log(people[userChoice]);

/* some code that transforms records */
people
  .map(person => `Hi, I am ${person.name} and I am a ${person.job}.`)
  .forEach(introduction => console.log(introduction));
  
/* different code that works with records */
const petOwners = people
  .filter(person => person.hasPet)
  .map(person => person.name);
  
console.log("Current pet owners:", petOwners)

【讨论】:

  • 感谢您与示例一起解释。现在我所有的疑惑都解决了。
【解决方案2】:

它就是empty 它既不是undefined 也不是null
const a = [,,,,]const a = new Array(4) 相同
这里 a 是一个没有填充元素且只有 length 属性的数组
这样做,let arr1 = new array() 然后console.log(arr1.length) 你会得到 0 作为输出。如果你这样做console.log(arr1),你会得到[ <4 empty items> ] 如果您像这样arr1.length = 4 更改 arr1 的长度属性,您将有一个长度属性 = 4 的空数组,但没有填充任何项目,因此这些插槽将是 empty,如果您这样做 console.log(typeof(arr1[0]),您将得到 @987654335 @ 只是因为没有其他可能的类型可以显示。并且 Array 的任何方法都不会应用于具有空元素的数组

所以,

空数组表示具有长度属性和未填充槽的数组

这与带有undefined 的数组不同,因为在JS 中undefined 是一种类型,您可以通过调用其上的所有数组方法来执行并获得结果,而带有empty 的数组没有类型也没有数组方法可以应用在它上面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2011-05-19
    • 2013-12-29
    相关资源
    最近更新 更多