数组中的empty剖析
一、首先empty是怎么来的
直接通过new Array来新建,手动修改数组的length,逗号之间没有任何数据等
const array = new Array(3);
console.log(array); //* (3) [empty × 3]
const array2 = [1, , 3];
console.log(array2); //* [1, empty, 3]
二、如何理解empty
但是按理说,未申明一个变量的值为undefined,这里不应该打印出[1, undefined, 3]么,这里为什么会打印出empty,而不是undefined呢?
const array2 = [1, , 3];
console.log(array2); //* [1, empty, 3]
console.log(array2[1]); //* undefined
又为什么我们打印数组中该empty位置的时候,却又输出undefined呢?
其实,js中万物皆对象,数组底层也是对象,函数底层也是对象;
那什么是对象呢?
对象就是一系列属性名值对,即某个属性名对应某个属性值;当我们遍历对象时,不在对象中的属性当然不会被访问到。
而在JS中,数组就是对象,甚至数组的一些遍历方法,在内部执行的时候,都是先将数组转化为对象。
可以使用console.dir() 来查看数组对象中的所有属性。
console.dir() 方法可以显示指定 JavaScript 对象的属性列表,并以交互式的形式展现。输出结果呈现为分层列表,包含展开/折叠的三角形图标,可用于查看子对象的内容。
换句话说,
console.dir()
是一种在控制台中查看指定 JavaScript 对象的所有属性的方法,开发人员可以通过这种方式轻松获取对象的属性。—— 引用于MDN之console.dir的使用
可以使用in来判断指定的属性是否在该对象或其原型链中
这个array2是一个长度为3的{0: 1, 2: 3}对象,没有索引为1的数组第二个元素,即数组的空元素empty表示空位;
也就是说,empty表示空位,数组对象没有该位置的索引属性!!!既没有属性,也没有属性值;
但是为什么「console.log(array[2]); //* undefined」呢?
因为可以输出一个对象中”不存在的属性“的值
const obj = {0: 1, 2: 3};
console.log(obj[1]); //* undefined
但是[1, , 3]又和[1, undefined, 3]的区别是什么呢?
这个array3是一个长度为3的{0: 1, 1: undefined, 2: 3}对象,索引为1的数组第二个元素 值为undefined;
undefined是一种数据类型, 在数组中表示这个位置的值未定义, 但它仍然指向某个内存地址, 这个内存地址指向的是undefined;
三、数组中的empty和undefined的主要区别
使用数组的forEach、map等方法遍历时会自动忽略空位跳过循环, 而使用for循环则会将empty转换为undefined并遍历.
四、如何理解forEach/map对数组中empty的怪异行为
因为在forEach/map底层在遍历的时候,会先判断该对象“坑位对应的索引”的属性是否存在,不存在的话则跳过循环;
const forEach = (arr, callback) => {
const len = arr.length; //? arr的长度
for (const i = 0; i < len; i++) {
if (i in arr) { //* 如果索引存在于数组对象中,调用回调函数
callback(arr[i], i, arr);
}
}
}