数组中的 empty

前言

该篇未参考任何资料,纯个人观点,探究一下让人好奇的现象。

正片

最近在想,数组中的 empty 究竟是个什么样的存在呢。这不是一种类型,不能与 undefinednull 相比;又显得怪怪的,为什么 foreach() 会跳过它。于是我想试试水。

创建一个带有 empty 元素数组最简单的方式就是使用 Array()

const arr = new Array(3);

console.log(arr); 
// [ <3 empty items> ]

现在,一步一步来看看。

别相信值

有时尝试着去比较了一下,像是这样:

const arr = new Array(3);

console.log(arr[0] == null); // true

// 再试试绝对相等
console.log(arr[0] === null); // false
console.log(arr[0] === undefined); // true

噢,原来这个值是 empty === undefined 呀。错了,看一个对比的例子:

const arr1 = new Array(3);

// 没动静??
arr1.forEach((item) => console.log(item));

// 字面量形式创建一个 `undefined` 数组
const arr2 = [undefined, undefined, undefined];

arr2.forEach((item) => console.log(item));
// undefined
// undefined
// undefined

那么如何理解这个相等呢,这里问一下,如果一个对象没有 key 值,你会拿到什么?那就是 undefined

const obj = {
    
    };

console.log(obj.name); // undefined

所以说,这不是 empty === undefined,而是没有拿到值,然后返回一个 undefined 糊弄人呢。

手动创建 empty

嗯,确实有一种方式可以创建出来,虽然这并没有什么用。

有一个操作符:delete。可以用于删除对象的值,或者说,可以删除一个字段。

const obj = {
    
    
	name: "obj"
};

console.log(obj); // { name: 'obj' }
console.log(obj.name); // obj

delete obj.name;

console.log(obj); // {}
console.log(obj.name); // undefined

好像有点意思了,可以预想,用到数组身上会怎样:

const arr = [1, 2, 3];
console.log(arr); // [ 1, 2, 3 ]

delete arr[0];
console.log(arr); // [ <1 empty item>, 2, 3 ]

结合普通对象一起看,就知道 empty 是什么表现了吧,那就是不存在这个字段,通过 new Array(length) 形式创建的数组就只有一个干瘪的长度而已。

现在还有一个问题未解答。

没有反应的 forEach()

在前面的例子当中,演示 empty 数组使用了 forEach(),却没有任何反应。

以前的猜想是,forEach() 应该是这样的一种实现吧:

function forEach(arr, callback) {
    
    
	const n = arr.length;
	for (let i = 0; i < n; i++) {
    
    
		callback(arr[i], i, arr);
	}
}

结合未执行的现象,可以说不可能是这样,只能说很相近,在其中还有一个判断,先看一个普通对象调用 forEach() 的表现:

const obj = {
    
    
	name: "obj",
	age: 18
};

// 使用 call() 借用
Array.prototype.forEach.call(obj, (v, i) => {
    
    
  console.log(v, i);
});

表现如一,没有动静。噢,应该使用类数组对象

const obj = {
    
    
	0: 0,
	1: 1,
	length: 2
};

Array.prototype.forEach.call(obj, (v, i) => {
    
    
	console.log(v, i);
});
// 0 0
// 1 1

现在删掉一个字段如何:

const obj = {
    
    
	1: 1,
	length: 2
};

Array.prototype.forEach.call(obj, (v, i) => {
    
    
	console.log(v, i);
});
// 1 1

好,完善一下自己的 forEach(),并且跟进测试:

function forEach(arr, callback) {
    
    
	const n = arr.length;
	for (let i = 0; i < n; i++) {
    
    
		if (i in arr) {
    
    
			callback(arr[i], i, arr);
		}
	}
}

const obj = {
    
    
	1: 1,
	length: 2
};

forEach(obj, (v, i) => {
    
    
	console.log(v, i);
});
// 1 1

这就理解了,为什么 forEach() 不会有反应,因为在执行前,判断了该字段是否存在在对象上。

-END-

猜你喜欢

转载自blog.csdn.net/qq_49661519/article/details/126809280