每日前端面试题-如何判断空对象,如何区分数据类型

一、如何判断空对象

①最常用 的是 Object.keys(obj).length === 0。它检查对象自身的、可枚举的属性名个数,性能好,能满足绝大多数业务场景。

②如果需要考虑不可枚举属性 (例如通过 Object.defineProperty 创建的属性),可以使用 Object.getOwnPropertyNames(obj).length === 0

③如果需要考虑最全面的情况(包括 Symbol 类型的属性键),则要使用 Reflect.ownKeys(obj).length === 0

④JSON.stringify(obj) === '{}' 方法虽然简单,但会忽略函数、undefined 等属性值,存在局限性,一般不推荐在严格的逻辑判断中使用。

1、JSON.stringify()

将对象转换为 JSON 字符串,然后判断其是否等于 '{}'

javascript 复制代码
const obj = {};
const isEmpty = JSON.stringify(obj) === '{}';
console.log(isEmpty); // true

const obj2 = { name: 'Tom' };
console.log(JSON.stringify(obj2) === '{}'); // false

缺点:

①性能问题:将整个对象序列化为字符串是一个相当耗时的行为

②如果属性值是函数,undefined,Symbol,JSON.stringigy()会忽略它们

javascript 复制代码
const obj = { a: undefined, b: function() {}, c: Symbol() };
console.log(JSON.stringify(obj) === '{}'); // true (但实际它有属性,所以判断不准确)
2、Object.keys() (最常用,兼顾性能和准确度)

Object.keys(obj) 返回对象自身可枚举属性名组成的数组。判断数组长度是否为 0 即可。

javascript 复制代码
const obj = {};
const isEmpty = Object.keys(obj).length === 0;
console.log(isEmpty); // true

const obj2 = { name: 'Tom' };
console.log(Object.keys(obj2).length === 0); // false

const obj3 = { a: undefined };
console.log(Object.keys(obj3).length === 0); // false (因为它确实有一个属性 'a')
3、Object.getOwnPropertyNames()可以发现不可枚举属性

返回所有属性名构成的数组,包含不可枚举属性,但是不包含Symbol类型的属性

javascript 复制代码
const obj = {};
Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false // 设置为不可枚举
});

console.log(Object.keys(obj).length === 0); // true (keys 无法发现不可枚举属性)
console.log(Object.getOwnPropertyNames(obj).length === 0); // false (发现了不可枚举属性)
4、Reflect.ownKeys()(最彻底最全面的,返回所有属性名构成的数组)
javascript 复制代码
const obj = {};
const sym = Symbol('key');
obj[sym] = 'symbol value';

Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false
});

console.log(Reflect.ownKeys(obj).length === 0); // false (包含了 Symbol 和不可枚举属性)
5、for...in(通常不推荐,但需要了解)

for...in 循环会遍历对象的可枚举属性 ,包括继承自原型链的属性。因此用它判断时,通常需要配合 hasOwnProperty 来过滤。

javascript 复制代码
function isEmpty(obj) {
            for(let key in obj) {
                if(obj.hasOwnProperty(key)) {
                    return false
                }
                return true
            }
        }
        const obj = {}
        console.log(isEmpty(obj))


        // 但是如果原型链上有可枚举属性
        const protoObj = {inherited: 'value'}
        // 以protoObj为原型创建新的对象
        const childObj = Object.create(protoObj)
        // true,(因为 childObj 自身没有属性,虽然原型链上有,但 hasOwnProperty 过滤掉了)
        console.log(isEmpty(childObj))

二、如何区分数据类型

javascript的数据类型分为两大类:

基本类型:string, number, boolean, undefined, null

引用类型:object, function, array, date

1、typeof操作符

typeof 适合判断 stringnumberbooleanundefinedsymbolbigintfunction。对于 null 和大部分对象类型,它只能返回 "object",无法进一步区分

javascript 复制代码
console.log(typeof 'hello');     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol());    // "symbol"
console.log(typeof 123n);        // "bigint"
console.log(typeof function(){});// "function" (函数是对象的一种,但 typeof 特殊处理)

// ---------- 著名的坑 ----------
console.log(typeof null);        // "object" (这是一个存在了20多年的bug)
console.log(typeof [1, 2, 3]);   // "object"
console.log(typeof {});          // "object"
console.log(typeof new Date());  // "object"
2、instanceof 操作符 (用于检查对象的具体类型)
javascript 复制代码
console.log([] instanceof Array);       // true
console.log([] instanceof Object);      // true (因为数组的原型链上也有 Object.prototype)
console.log({} instanceof Object);      // true
console.log(new Date() instanceof Date);// true
console.log(/regex/ instanceof RegExp); // true

// 基本类型用 instanceof 通常为 false
console.log('hello' instanceof String); // false (除非是 new String('hello') 创建的对象)
3、Object.prototype.toString.call() (终极方案,最准确)

这是最强大、最准确的类型判断方法。它可以返回任何数据类型的内部 [[Class]] 属性。

javascript 复制代码
const toString = Object.prototype.toString;

console.log(toString.call('hello'));      // "[object String]"
console.log(toString.call(42));           // "[object Number]"
console.log(toString.call(true));         // "[object Boolean]"
console.log(toString.call(undefined));    // "[object Undefined]"
console.log(toString.call(null));         // "[object Null]"
console.log(toString.call(Symbol()));     // "[object Symbol]"
console.log(toString.call(123n));         // "[object BigInt]"
console.log(toString.call([]));           // "[object Array]"
console.log(toString.call({}));           // "[object Object]"
console.log(toString.call(function(){})); // "[object Function]"
console.log(toString.call(new Date()));   // "[object Date]"
console.log(toString.call(/regex/));      // "[object RegExp]"
console.log(toString.call(new Error()));  // "[object Error]"
console.log(toString.call(document));     // "[object HTMLDocument]"
console.log(toString.call(globalThis));   // "[object global]" 或 "[object Window]"
相关推荐
牛奶6 小时前
AI辅助开发最佳实践:2026年新方法
前端·aigc·ai编程
C澒7 小时前
微前端容器标准化:公共能力标准化
前端·架构
Setsuna_F_Seiei7 小时前
AI 对话应用之 JS 的流式接口数据处理
前端·javascript·ai编程
青柠代码录8 小时前
【Vue3】Vue Router 4 路由全解
前端·vue.js
无限大68 小时前
《AI观,观AI》:专栏总结+答疑|吃透核心,解决你用AI的所有困惑
前端·后端
蜡台9 小时前
element-ui 2 el-tree 内容超长滚动条不显示问题
前端·vue.js·elementui·el-tree·v-deep
小小小小宇10 小时前
软键盘常见问题(二)
前端
小小小小宇10 小时前
软键盘常见问题
前端
小小小小宇11 小时前
富文本编辑器知识体系(三)
前端
小小小小宇11 小时前
富文本编辑器知识体系(二)
前端