数组中的 empty
前言
该篇未参考任何资料,纯个人观点,探究一下让人好奇的现象。
正片
最近在想,数组中的 empty 究竟是个什么样的存在呢。这不是一种类型,不能与 undefined 和 null 相比;又显得怪怪的,为什么 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); // objdelete 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-
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
