在 JavaScript 中判断对象是否空的正确姿势

1,882 阅读4分钟

本文由五柳翻译、润色,原文地址 ,作者:Samantha Ming

下面是一个检查对象是否为空的代码片段。对于新的浏览器而言,你可以使用普通的 JS 和 ES6 的语法 Object.keys。但是,为了支持旧的浏览器,你可以安装 Lodash 和使用它的 isEmpty 方法。

const empty = {};
/* -------------------------
  针对新浏览器的普通 JS
----------------------------*/
Object.keys(empty).length === 0 && empty.constructor === Object
// true
/* -------------------------
  针对旧浏览器的 lodash 语法
----------------------------*/
_.isEmpty(empty)
// true

1 什么是普通的(Vanilla)的 JavaScript?

普通的(Vanilla)不是一个新的框架或库。它是指常规的 JavaScript,而不使用像 Lodash 或 JQuery 之类的库。

2 在新浏览器中检查空对象

我们可以使用内置的 Object.keys 方法来检查一个空对象:

const empty = {};
Object.keys(empty).length === 0 && empty.constructor === Object;

2.1 为什么我们需要一个额外的构造方法 constructor 检查?

你可能会想为什么我们需要检查构造方法 constructor。因为,这是为检查了覆盖其包裹的实例。在 JavaScript 中,我们有 9 个内置的构造方法。

new Object();
new String();
new Number();
new Boolean();
new Array();
new RegExp();
new Function();
new Date();

因此,我们可以使用 new Object() 来创建一个空的对象。注意⚠️:你不应该使用这个构造方法来创建一个对象。这被认为是不好的做法,详细讲解可以查看 Airbnb Style GuideESLint

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 😱

可以看到,这里我们得到了不正常的结果 😱。

2.2 检查构造方法 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 ✅

漂亮!我们覆盖了这些边缘的例子 👍

2.3 用其他值来测试检查空对象方法

接下来,用一些其他值来测试我们的方法,并且看看这会返回什么 🧪

function isEmptyObject(value) {
  return Object.keys(value).length === 0 && value.constructor === Object;
}

目前看来很好,对于不是对象它会返回 false

isEmptyObject(100)  // false
isEmptyObject(true) // false
isEmptyObject([])   // false

🚨 但是,请注意(小心)!以下这些值将会抛出异常。

// TypeError: Cannot covert undefined or null ot object
goodEmptyCheck(undefined)
goodEmptyCheck(null)

2.4 针对 null 和 undefined,改良检查空对象方法

如果你不想它抛出 TypeError 的异常,你可以添加一个额外的检查。

let value;
value // 👈 null and undefined check
 && Object.keys(value).length === 0 && value.constructor === Object;
value = null;       // null
value = undefined;  // undefined

完美,已经不会抛出错误了 😁

3 在旧的浏览器检查空对象

如果你需要支持旧浏览器呢?见鬼,我在和谁开玩笑!我们都知道当我们说旧浏览器时,指的是 IE 浏览器 😂。这个时候,我们有两个选择,我们可以选择普通的(vanilla) JavaScript 或利用库。

3.1 使用普通的 JavaScript 检查空对象

使用普通的 JavaScript 的方式没有那么简洁。但是,它确实起了作用 👍。

function isObjectEmpty(value) {
  return Object.prototype.toString.call(value) === "[object Object]" && JSON.stringify(value) === "{}"
}

对于对象它会返回 true

isObjectEmpty({});           // true ✅
isObjectEmpty(new Object()); // true ✅

很好地是,它不会被我们的构造函数所欺骗 😉

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 的时候,它不会抛出 TypeError 的异常。

isObjectEmpty(null);      // false
isObjectEmpty(undefined); // false

3.2 使用外部的库(libraries)来检查空对象

有很多外部的库可以用来检查空对象。并且,它们大多数对旧的浏览器有很好的支持 👍

Lodash

_.isEmpty({});
// true

Underscore

_.isEmpty({});
// true

jQuery

jQuery.isEmptyObject({});
// true

4 对比普通的 JavaScript、库

这个答案需要应情况而定!我非常喜欢尽可能地去使用普通的 JavaScript,因为我不喜欢外部库的开销。而且,对于小型应用,我也非常懒得去安装额外的库。但是,如果你的应用已经安装了外部的库,你可以继续使用它。因为,你比任何人都了解你的应用程序。所以,可以选择最合适你的情况 👍

❤️ 爱心三连击

写作不易,可以的话麻烦点个赞,这会成为我坚持写作的动力!!!

我是五柳,喜欢创新、捣鼓源码,专注于 Vue3 源码、Vite 源码、前端工程化等技术分享,欢迎关注我的微信公众号:Code center