每天一个填坑小细节之判断空对象
在现代浏览器中使用Object.keys()判断
const empty = {};
Object.keys(empty).length === 0 && empty.constructor === Object;
为何加了一个额外的constructor判断?
你可能很好奇,为何加了一个constructor检测?
且听我给你一一分析
我们都知道在js中有9种内置的构造函数
new Object();
new String();
new Number();
new Boolean();
new Array();
new RegExp();
new Function();
new Date();
我们可以用new Object()来创建一个对象
但是最好不要这么用
const obj = new Object();
Object.keys(obj).length === 0; // true
这样,使用Object.keys去判断, 当对象为空的时候返回true ✅.
但是,但我们用其他构造函数创建实例会怎么样?
function badEmptyCheck(value) {
return Object.keys(value).length === 0;
}
badEmptyCheck(new String()); // true 😱
badEmptyCheck(new Number()); // true 😱
badEmptyCheck(new Boolean()); // true 😱
badEmptyCheck(new Array()); // true 😱
badEmptyCheck(new RegExp()); // true 😱
badEmptyCheck(new Function()); // true 😱
badEmptyCheck(new Date()); // true 😱
奇怪的事情发生了
少了constructor判断以后,都为真
使用constructor检测来避免其他构造函数的创建的空对象
function goodEmptyCheck(value) {
Object.keys(value).length === 0
&& value.constructor === Object; // 👈 constructor check
}
goodEmptyCheck(new String()); // false ✅
goodEmptyCheck(new Number()); // false ✅
goodEmptyCheck(new Boolean()); // false ✅
goodEmptyCheck(new Array()); // false ✅
goodEmptyCheck(new RegExp()); // false ✅
goodEmptyCheck(new Function()); // false ✅
goodEmptyCheck(new Date()); // false ✅
这样一来,避免了其他情况的影响
其他特殊值的判断,null, undefined
当碰到null, undefined时,会抛出错误
// TypeError: Cannot covert undefined or null ot object
goodEmptyCheck(undefined);
goodEmptyCheck(null);
为了解决这个问题,可以加一个存在性判断, 解决错误抛出
function goodEmptyCheck(value) {
value && Object.keys(value).length === 0
&& value.constructor === Object; // 👈 constructor check
}
旧浏览器中使用 Object.prototype.toString.call()判断
旧浏览器中不支持ES新方法
我们使用Object.prototype.toString.call()配合JSON.stringify(value) === '{}'来判断
function isObjectEmpty(value) {
return (
Object.prototype.toString.call(value) === '[object Object]' &&
JSON.stringify(value) === '{}'
);
}
碰到空对象时会正确输出
isObjectEmpty({}); // true ✅
isObjectEmpty(new Object()); // true ✅
不需要使用constructor检测
这种判断方式,避免了其他构造函数的影响
isObjectEmpty(new String()); // false ✅
isObjectEmpty(new Number()); // false ✅
isObjectEmpty(new Boolean()); // false ✅
isObjectEmpty(new Array()); // false ✅
isObjectEmpty(new RegExp()); // false ✅
isObjectEmpty(new Function()); // false ✅
isObjectEmpty(new Date()); // false ✅
null和undefined也可以正确处理
当然,即使是 null和undefined,也不需要额外处理
isObjectEmpty(null); // false
isObjectEmpty(undefined); // false
其他方法:借助第三方库
Lodash
_.isEmpty({});
// true
Underscore
_.isEmpty({});
// true
jQuery
jQuery.isEmptyObject({});
// true